【问题标题】:Reducing time complexity for Python, finding numbers with same digits降低 Python 的时间复杂度,查找具有相同数字的数字
【发布时间】:2021-11-30 23:19:17
【问题描述】:

我正在编写返回具有相同数字的下一个更大数字的代码。我认为我的解决方案很快,但在测试时我意识到我的时间复杂度非常糟糕。

def next_bigger(n):
    j = n
    for i in range(n):
        n+=1
        if sorted(str(j)) == sorted(str(n)):
            return n
    return -1

print(next_bigger(143255555555555553223))

有没有更快的方法来实现这个算法。有没有办法让我替换 sorted() 并删除 for 循环?

注意:如果找不到更大的数字,则返回 -1。忘记加了,以为很清楚。

注2:对不起,我不擅长写问题。原始算法有 while True 而不是 for 循环。这就是为什么它在按原样运行时返回 -1 的原因,使用 while True 会给出正确的答案,但需要时间。

一些输入:123 -> 132 || 2532 -> 3225 || 543890432 -> 543892034 || 143255555555555553223 -> 143255555555555553232 ||

【问题讨论】:

  • 11的情况下你期望返回什么?目前还不清楚是否必须使用所有数字。
  • 您的算法不仅速度很慢,而且也不正确。 print(next_bigger(1999)) 错误地打印 -1,而不是 9199
  • @Stef 我漂亮确定OP意味着如果输入1999,则响应应该是-1,因为9199大于原始数字,而999 不包括1
  • @NathanielFord 我不明白你的评论。 OP 正在寻找具有相同数字的下一个更大的数字。与 1999 相同的数字只有 4 个:1999、9199、9919 和 9991。1999 之后的下一个更大的数字是 9199。
  • @stef 我可能对 OP 正在寻找什么有误解 - 如果我有数字 1、2 和 3,我会说“3 是最大的”而“2 是下一个”最大'。暗示他们正在寻找一个较小的数字 - 但我同意您可以将其解析为他们正在寻找一个更大的数字,这与他们的代码一致。举例说明会有所帮助! OP:给我们一些示例输入以及您期望发生的情况!

标签: python performance math


【解决方案1】:

您的根本问题是,您从最高有效数字开始并从那里开始工作,而您想从最低有效数字开始并找到它可以替换的其他最低有效数字。

因此:如果您有号码432,则2 想与3 交换以创建423,这是具有相同数字的下一个最小数字。这意味着,从您希望以递增的重要性顺序查看每个递增数字的最小数字开始。 (在上面的例子中,首先是3,然后是4)。最低有效位小于的第一个数字,它应该替换。最后,如果没有比它大的数字(即419 - 9 是最大的数字),你应该再试一次,但从倒数第二个数字开始,依此类推。只有当您以这种方式用尽所有数字时,您才应该返回错误值。

不过,这种方法最多只能给出 O(len(n)^2) 时间,因为它需要两次迭代(对于每个数字,从最后一个开始并向前移动,检查从倒数第二个开始的每个数字并继续前进)。可能有更好的方法我没有想到。

有一些边缘情况需要处理(如果你的 n 是 0 或 1 长度怎么办?数字 100 会发生什么?),但这是你要处理的核心:

for alpha in range(len(n), -1, -1):
    alpha_num = n[alpha]
    for omega in range(len(n-1), -1, -1):
        omega_num = n[omega]
        if alpha_num < omega_num:
            n[omega] = alpha_num
            n[alpha] = omega_num
            return n

附录:下一个最大

根据制作的 cmets,我怀疑我误解了目标。并不是你想找到某个数字b,它严格小于a,并且使用所有相同的数字,并且是所有这些数字中最大的,而是你想找到一个b严格大于a 并且使用所有相同的数字并且是所有此类数字中最小的。

因此,您可能会有以下示例:

432 -> No result
567 -> 576
627 -> 672
587 -> 758
672 -> 726

您将需要使用类似的方法,从最低有效数字开始,向左移动以找到仍然更大的最小数字并交换。但这并不涵盖所有情况。 (当我有超过一分钟的时间来写出算法时,我会回到这个,但这可能有助于你朝着正确的方向前进。)

【讨论】:

  • “这种方法充其量只需要 O(n^2) 时间” 这句话令人难以置信的混乱。在 OP 的问题中,n 是原始数字,而不是该数字的位数。 OP 的算法直接对数字进行迭代。但是您的建议是对n 的数字进行操作,这比OP 的方法效率更高。事实上,您的方法听起来非常接近 next permutation algorithm,它的位数是线性的,而不是您建议的二次方。
  • 另外我不明白你的意思 “你的根本问题是你从最重要的数字开始并从那里开始工作”
  • @Stef 我不同意这“令人难以置信”令人困惑,因为n 是“输入长度”的惯用语,在这种情况下,n 甚至不是一个数字——它是一个字符数组。但无论如何,我澄清说我的意思是长度。
  • 这对你来说可能是惯用的,但对于 OP 来说显然不是那么明显。在 OP 显示的代码中,n 是一个整数,而不是一个字符列表。
  • @Stef 我认为您在 cmets 中不必要地好斗。我做了修改,除非在你的书中没有将它从“非常不清楚”变为“清晰”,否则我不确定是否需要进一步评论?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-14
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 2014-03-30
  • 2017-02-20
  • 1970-01-01
相关资源
最近更新 更多