[英]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:使用的逻辑:
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
) 是多少,使得:
0 <= N < N2
, and 0 <= N < N2
,和N
and N2
are the sameN
和N2
中出现的次数相同(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_l
和i_r
。 i_l
and i_r
will always be on the left and right respectively. i_l
和i_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_l
和i_r
从N
的最低有效侧开始,新数字是满足条件 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
;还要注意,例如输入
9
或111
; 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.