简体   繁体   English

使用排列找到下一个最大的数字

[英]Using permutations to find the next biggest number

Create a function that takes a positive integer and returns the next bigger number that can be formed by rearranging its digits.创建一个函数,它接受一个正整数并返回可以通过重新排列其数字形成的下一个更大的数字。

To accomplish this I used the following code:为此,我使用了以下代码:

Logic used:使用的逻辑:

  1. Write a script do all the permutations of the number eg 123 -> 132,321,231,...编写一个脚本来完成数字的所有排列,例如 123 -> 132,321,231,...
  2. select the largest number from the possible combinations从可能的组合中选择最大的数字
  3. if that number is bigger than original number provided it returns that number - if not it returns -1.如果该数字大于原始数字,则返回该数字 - 如果不是,则返回 -1。

Code Block:代码块:

import itertools
def next_bigger(n):
    # [int(x) for x in str(n)] ex: convert 123 to array [1,2,3]
    # list(set(itertools.permutations... gives you a list of permutation e.g. [[1,3,2],[3,2,1],[2,3,1],...]
    # [int(''.join(map(str,x))) for x in ...  converts each permuted list into a number e.g. convert [2,3,1] -> 231
    # for num in sorted(...if num>n: --> if 321 is bigger than 123, return it
    
     for num in sorted([int(''.join(map(str,x))) for x in list(set(itertools.permutations([int(x) for x in str(n)])))]):
        if num>n:
            return num
        else:
            return -1

Expected Output:预期输出:

nextBigger(num: 12)   // returns 21
nextBigger(num: 513)  // returns 531
nextBigger(num: 2017) // returns 2071
nextBigger(num: 9)   // returns nil
nextBigger(num: 111) // returns nil
nextBigger(num: 531) // returns nil

Actual Output: Test results fail实际输出: Test results fail

Solution Attempt#2:解决方案尝试#2:

import itertools
def next_bigger(n):
    # [int(x) for x in str(n)] ex: convert 123 to array [1,2,3]
    # list(set(itertools.permutations... gives you a list of permutation e.g. [[1,3,2],[3,2,1],[2,3,1],...]
    # [int(''.join(map(str,x))) for x in ...  converts each permuted list into a number e.g. convert [2,3,1] -> 231
    # for num in sorted(...if num>n: --> if 321 is bigger than 123, return it
    
    a = []
    results = 0
    for num in sorted([int(''.join(map(str,x))) for x in list(set(itertools.permutations([int(x) for x in str(n)])))]):
        if num>n:
            a.append(num)
    results = a[0]
            
    return results

Expected output: Passes all tests cases except for long numbers预期输出:通过除长数字以外的所有测试用例

What's wrong with my code?我的代码有什么问题?

The title says 'using permutations', but you don't need to use permutations for this.标题说“使用排列”,但您不需要为此使用排列。

The order of the tuples itertools.permutations emitted is defined;定义了发出的元组itertools.permutations的顺序; but unfortunately it will not always produce digits that when combined are in increasing order.但不幸的是,它并不总是产生组合时按递增顺序排列的数字。 Also calculating all permutations will take an extremely long time if the number of digits is very large.如果位数非常大,计算所有排列也将花费非常长的时间。

To rephrase the question: for any given N , what is the smallest number ( N2 ) such that:重新表述这个问题:对于任何给定的N ,最小的数字 ( N2 ) 是多少,使得:

  1. 0 <= N < N2 , and 0 <= N < N2 ,和
  2. The number of times each digit appears in N and N2 are the same每个数字在NN2中出现的次数相同

(if N2 doesn't exist, return None ) (如果N2不存在,则返回None

We could start from N and do N+=1 until condition 2 is satisfied, or until condition 2 can no longer be satisfied because the total number of digits in N increased.我们可以从N开始,做N+=1直到满足条件 2,或者直到条件 2 不再满足,因为N的总位数增加了。 (An int in Python 3 has no defined limit for how big it can get, so we would not get an overflow.) This is still (on average) extremely slow if N is very large, however it will in theory eventually return. (Python 3 中的int没有定义它可以有多大的限制,所以我们不会发生溢出。)如果N非常大,这仍然(平均而言)非常慢,但理论上它最终会返回。

Here is how I would solve this:这是我将如何解决这个问题:

def main(N):
    n=list(map(int,str(N)))
    for i_r in reversed(range(len(n))):
        for i_l in reversed(range(i_r)):
            if n[i_l]<n[i_r]:
                t_l=n[i_l]
                t_r=n[i_r]
                n[i_l]=t_r
                n[i_r]=t_l
                return int(''.join(map(str,n)))
    return None

First convert N into a list of digits (while preserving the order).首先将N转换为数字列表(同时保留顺序)。 This will make N easier to work on.这将使N更容易处理。

Make 2 markers i_l and i_r .制作 2 个标记i_li_r i_l and i_r will always be on the left and right respectively. i_li_r将始终分别位于左侧和右侧。 They will start on the least significant (ie right) side of N .它们将从N的最不重要(即右侧)一侧开始。

They will go through N like this for example:例如,他们将像这样通过N

4321    4321    4321    4321    4321    4321
  lr     l r    l  r     lr     l r     lr  

When i_l < i_r , swap those digits to make a bigger number, which satisfies condition 1. Since i_l and i_r start from the least significant side of N , that new number is the smallest number that satisfies condition 2. If that number doesn't exist, the function returns None .i_l < i_r ,交换这些数字以形成一个更大的数字,满足条件 1。由于i_li_rN的最低有效侧开始,新数字是满足条件 2 的最小数字。如果该数字不满足存在,该函数返回None

(The return None is actually unnecessary, as functions by default return None , however explicitly stating it makes it more clear that this is the intended behavior.) return None实际上是不必要的,因为函数默认返回None ,但是明确说明它可以更清楚地表明这是预期的行为。)

With this solution, even if N is 10000 digits, the function will return in a reasonable amount of time.使用此解决方案,即使N是 10000 位数字,该函数也会在合理的时间内返回。

You need the next biggest number, but currently you pick any permutation-number greater than the input-number.您需要下一个最大的数字,但目前您选择any大于输入数字的排列数字。 You should be the picking the minimum among such numbers

Also notice, for example for input 9 or 111 ;还要注意,例如输入9111 there are no other permutations;没有其他排列; so you might just want to return the next biggest-permutation or None .所以你可能只想返回next biggest-permutation or None

You might consider modifying to this:您可以考虑修改为:

import itertools
def next_bigger(n):
    # [int(x) for x in str(n)] ex: convert 123 to array [1,2,3]
    # list(set(itertools.permutations... gives you a list of permutation e.g. [[1,3,2],[3,2,1],[2,3,1],...]
    # [int(''.join(map(str,x))) for x in ...  converts each permuted list into a number e.g. convert [2,3,1] -> 231
    # for num in sorted(...if num>n: --> if 321 is bigger than 123, return it
    
     minval = -1
     for num in sorted([int(''.join(map(str,x))) for x in list(set(itertools.permutations([int(x) for x in str(n)])))]):
        if num>n:
            if minval == -1 or minval > num:
                minval = n
     return minval

Appropriate test-cases:适当的测试用例:

nextBigger(num: 1176) //should return 1617

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM