繁体   English   中英

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

[英]Using permutations to find the next biggest number

创建一个函数,它接受一个正整数并返回可以通过重新排列其数字形成的下一个更大的数字。

为此,我使用了以下代码:

使用的逻辑:

  1. 编写一个脚本来完成数字的所有排列,例如 123 -> 132,321,231,...
  2. 从可能的组合中选择最大的数字
  3. 如果该数字大于原始数字,则返回该数字 - 如果不是,则返回 -1。

代码块:

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

预期输出:

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

实际输出: Test results fail

解决方案尝试#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

预期输出:通过除长数字以外的所有测试用例

我的代码有什么问题?

标题说“使用排列”,但您不需要为此使用排列。

定义了发出的元组itertools.permutations的顺序; 但不幸的是,它并不总是产生组合时按递增顺序排列的数字。 如果位数非常大,计算所有排列也将花费非常长的时间。

重新表述这个问题:对于任何给定的N ,最小的数字 ( N2 ) 是多少,使得:

  1. 0 <= N < N2 ,和
  2. 每个数字在NN2中出现的次数相同

(如果N2不存在,则返回None

我们可以从N开始,做N+=1直到满足条件 2,或者直到条件 2 不再满足,因为N的总位数增加了。 (Python 3 中的int没有定义它可以有多大的限制,所以我们不会发生溢出。)如果N非常大,这仍然(平均而言)非常慢,但理论上它最终会返回。

这是我将如何解决这个问题:

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

首先将N转换为数字列表(同时保留顺序)。 这将使N更容易处理。

制作 2 个标记i_li_r i_li_r将始终分别位于左侧和右侧。 它们将从N的最不重要(即右侧)一侧开始。

例如,他们将像这样通过N

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

i_l < i_r ,交换这些数字以形成一个更大的数字,满足条件 1。由于i_li_rN的最低有效侧开始,新数字是满足条件 2 的最小数字。如果该数字不满足存在,该函数返回None

return None实际上是不必要的,因为函数默认返回None ,但是明确说明它可以更清楚地表明这是预期的行为。)

使用此解决方案,即使N是 10000 位数字,该函数也会在合理的时间内返回。

您需要下一个最大的数字,但目前您选择any大于输入数字的排列数字。 You should be the picking the minimum among such numbers

还要注意,例如输入9111 没有其他排列; 所以你可能只想返回next biggest-permutation or None

您可以考虑修改为:

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

适当的测试用例:

nextBigger(num: 1176) //should return 1617

暂无
暂无

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

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