我在理解Leet代码中的“快乐数字”问题的一种解决方案的时间复杂度分析时遇到一些困难,由于对复杂度分析的怀疑,我将其粗体显示,并非常感谢您的建议
这是问题:
链接:https://leetcode.com/problems/happy-number/
问题:
编写一种算法来确定数字是否“幸福”。 一个快乐的数字是由以下过程定义的数字:从任何正整数开始,用该数字的平方和代替该数字,然后重复该过程,直到该数字等于1(它将停留在该位置),否则它就会循环在不包含1的循环中无休止地进行下去。此过程以1结尾的数字是快乐数字。
示例:
输入:19
输出:true
说明:
1 ^ 2(1的平方)+ 9 ^ 2 = 82
8 ^ 2 + 2 ^ 2 = 68
6 ^ 2 + 8 ^ 2 = 100
1 ^ 2 + 0 ^ 2 + 0 ^ 2 = 1
代码如下:
class Solution(object):
def isHappy(self, n):
#getnext function will compute the sum of square of each digit of n
def getnext(n):
totalsum = 0
while n>0:
n,v = divmod(n,10)
totalsum+=v**2
return totalsum
#we declare seen as a set to track the number we already visited
seen = set()
#we stop checking if: either the number reaches one or the number was visited #already(ex.a cycle)
while n!=1 and (n not in seen):
seen.add(n)
n = getnext(n)
return n==1
注意:如果需要解释代码的工作原理,请随时告诉我
时间复杂度分析:
时间复杂度:O(243 * 3 + logN + loglogN + log loglog N)... = O(logN)。
查找给定数字的下一个值的成本为O(log n),因为我们正在处理数字中的每个数字,并且数字中的数字位数由logN给出。 我的疑问:为什么数字中的位数由logN给出?这里的N是什么?特定数字或其他值的值?
要计算总时间复杂度,我们需要仔细考虑链中有多少个数字,以及它们有多大。
我们在上面确定,一旦数字低于243,就不可能再回到243以上。因此,基于我们的浅层分析,我们可以确定一旦数字低于243,就不可能终止操作还需要243多个步骤。
每个数字最多包含3位数字。经过更多的分析,我们可以将最长的数字链的长度替换为243,并将其替换为243以下的最长数字链的长度,但是由于常量无论如何都不重要,因此我们无需担心。 我的疑问:我认为上一段与243 * 3的时间复杂度成分有关,但我不明白为什么我们将243乘以3
对于大于243的n,我们需要考虑链中大于243的每个数字的成本。通过一点数学运算,我们可以证明在最坏的情况下,这些成本为O(log n)+ O(log log n)+ O(log log log N)...对我们来说幸运的是,O(logN)是主要部分,而其他所有参数相比而言都是很小的(总的来说,它们的总和小于logN) ,因此我们可以忽略它们。 我的疑问:对于大于243的n,O(log log n)O(log log log N)背后的原因是什么?
答案 0 :(得分:1)
好吧,我对第一个疑问的猜测是,以10为底的数字的位数是由它的值(N)取为以10为底的对数的整数。因此,例如1023将有floor(log10(1023))
位数字,即3。所以,是的,N是数字的值。时间复杂度上的log
表示对数,而不是对数2或e的对数。
关于第二个疑问,这可能与将数字减少到243以下所需的工作有关,但是我不确定。一旦完成工作,我将编辑此答案。
答案 1 :(得分:0)
假设N
有M
位数字。比getnext(N) <= 81*M
。当N
仅具有9
时,将发生平等。
当N < 1000
时,即最多3位,getnext(N) <= 3*81 = 243
。现在,您最多只能拨打getnext(.)
次O(243)
来确定N
是否确实很开心。
如果为M > 3
,则getnext(N)
的位数必须小于M
。尝试使用getnext(9999)
,getnext(99999)
等[1]。
注释:
[1]在N
上添加一个数字最多可以使其10*N + 9
,即在末尾添加9
。但是位数只会增加到M+1
。这是N
和M
之间的对数关系。因此,N
和81*M
之间保持着相同的关系。