我在this上有codewars.com问题的解决方案,当我在Sublime中运行时有效,但是当我尝试提交时,我收到此错误:
流程已终止。完成时间超过12000毫秒
为什么我的代码会超时?
我们的服务器配置为只允许一定的时间来执行代码。在极少数情况下,服务器可能会承担太多工作,而且根本无法有效地运行代码。大多数情况下,这个问题是由效率低下的算法引起的。如果您多次看到此错误,则应尝试进一步优化代码。
该功能的目标是通过重新排列给定数字的数字,找到您可以制作的给定数字后的下一个最大数字。例如,如果我被给予216,我将需要返回261.
这是我现在的代码:
import itertools
def next_bigger(n):
# takes a number like 472 and puts it in a list like so: [4, 7, 2]
num_arr = [int(x) for x in str(n)]
perms = []
total = ''
# x would be a permutation of num_arr, like [7, 2, 4]
for x in itertools.permutations(num_arr):
for y in x:
total += str(y)
perms.append(int(total))
total = ''
# bigger is all permutations that are bigger than n,
# so bigger[0] is the next biggest number.
# if there are no bigger permutations, the function returns -1
bigger = sorted([x for x in perms if x > n])
return bigger[0] if bigger else -1
我是Python新编码的新手,所以我制作的一些错误会导致我的代码效率极低吗?欢迎任何建议。
答案 0 :(得分:2)
感谢你们给我的所有帮助。我最终使用下一个词典排列算法
从here找到了一个解决方案这是我提供的here解决方案的整理版本:
def next_bigger(n):
# https://www.nayuki.io/res/next-lexicographical-permutation-algorithm/nextperm.py
# https://www.nayuki.io/page/next-lexicographical-permutation-algorithm
# Find non-increasing suffix
arr = [int(x) for x in str(n)]
i = len(arr) - 1
while i > 0 and arr[i - 1] >= arr[i]:
i -= 1
if i <= 0:
return -1
# Find successor to pivot
j = len(arr) - 1
while arr[j] <= arr[i - 1]:
j -= 1
arr[i - 1], arr[j] = arr[j], arr[i - 1]
# Reverse suffix
arr[i : ] = arr[len(arr) - 1 : i - 1 : -1]
return int(''.join(str(x) for x in arr))
答案 1 :(得分:1)
你为什么得到TLE (超出时限)?
因为您的算法具有错误的复杂性。使用 3 元素列出的列表会有多少排列?只有 6 。但是如果我们使用带有 23 元素的列表呢?的 25852016738884976640000 即可。 这太长了时间限制。
所以,如果你想解决这个问题,你必须找到没有排列的解决方案。请重新考虑如何编写数字。数字271大于216,因为第二位置上的数字具有更大的值7> 1。
因此,您的解决方案必须找到两个数字并交换位置。左边的数字必须小于第二个数字。
例如 - 对于111115444474444,您应该找到 5 和 7 。
然后你交换它们 - 现在你应该从第一个位置右侧对子列表进行排序。
例如,在交换了值(11111 7 4444 5 4444)后,您必须排序(444454444) - &gt; (444444445)。现在合并所有,你有解决方案。
import functools
def next_bigger(a):
a = map(int, str(a))
tmp = list(reversed(a))
for i, item_a in enumerate(reversed(a)):
for j in (range(i)):
if item_a < tmp[j]:
#you find index of number to swap
tmp[i]=tmp[j]
print(list(reversed(tmp[i:])))
tmp[j]=item_a
fin = list(reversed(tmp[i:])) + sorted(tmp[:i])
return functools.reduce(lambda x,y: x*10+y, fin)
return -1
答案 2 :(得分:0)
您应该按照desc顺序对num_arr进行排序,并通过组合结果来创建数字。
由于需要OP,下一个最大,OP需要从右边开始检查,哪个右边的数字大于它的左边数字并旋转它们的位置。
以下是最终代码:
def next_bigger(n):
num_arr = [int(x) for x in str(n)]
i = 0
i = len(num_arr) - 1
while(i > 0):
if num_arr[i] > num_arr[i-1]:
a = num_arr[i]
num_arr[i] = num_arr[i-1]
num_arr[i-1] = a
break
else:
i = i-1
newbig = "".join(str(e) for e in num_arr)
return int(newbig)
答案 3 :(得分:0)
现在我编辑计算下一个更大的元素。
def perms(s):
if(len(s)==1):
return [s]
result=[]
for i,v in enumerate(s):
result += [v+p for p in perms(s[:i]+s[i+1:])]
return result
a=input()
b=perms(str(a))
if len(b)!=1:
for i in range(0,len(b)):
if b[i]==a:
print (b[i+1])
break
else:
print ("-1")
答案 4 :(得分:0)
一种简单的回溯方法是一次考虑一个数字。从最重要的数字开始,选择您留下的最小数字,这不会阻止新数字超出输入。这将始终通过再现输入开始,然后将不得不回溯到倒数第二个数字(因为最后一个数字没有任何其他选择)。对于像897654321这样的输入,回溯将立即级联到开头,因为没有更大的数字可以在任何中间槽中尝试。