假设我们在解决Java问题时遇到了以下问题。
用户输入的密码长度在5个字符到35个字符之间(含5个字符)。我们需要确保它们不会连续重复3次相同的字符。
boolean has3CharsInARow(char [] password){
for(int left=0, middle=1, right=2; right < password.length; left++, middle++, right++){
if(password[left]==password[middle] && password[middle]==password[right]){
return true;
}
}
return false;
}
时间复杂度是多少(为简单起见,假设使用大O符号和最坏的情况)?
我的想法是我们不知道密码中3个字符的位置,因此我们必须搜索所有适当的字符 字符肯定。但是我正在努力将其归类为n个字符的O(1)或O(n)。
O(1)的参数是什么?在上下文的情况下,我们知道它最多只能对密码进行限制 长度为35个字符。因此,在最坏的情况下,我们找不到3个重复的字符,而是扫描O(34)33以找到正确的索引2至34和另外1个 当right为35时,我们退出循环保护,最后返回false。由于34是常数,因此通常说O(34)= O(1),这是恒定的时间复杂度。
O(n)的参数是什么?好吧,我们关心函数的时间效率如何随着输入长度的增加而变化。要是我们 假设T(n)是has3CharsInARow的运行时间,我们可以说T随密码长度的每单位或字符增加而线性增长。因此T在函数O(n)的类别中。
我们在哪里画O(1)和O(n)之间的线?
编辑: 由于一个回答者写了O(n),那么这是否也意味着该等效方法也是O(n)?
boolean has3CharsInARow(char [] password){
switch(password.length){
case 0:
case 1:
case 2:
return false;
case 3: return password[0] == password[1] && password[1] == password[2];
case 4: return password[0] == password[1] && password[1] == password[2] ||
password[1] == password[2] && password[2] == password[3];
...
case 35: return ...;
}
}
答案 0 :(得分:1)
算法的时间复杂度为O(n)
。这里真的没有摆动空间。这是数学和算法分析。为了完整起见,最佳情况是O(1)
,平均情况下,最坏情况是O(n)
。
我认为混淆是由于人们不了解大O表示法的含义以及如何解释它。您说(我的意思是):“但是如果我将输入的大小限制为一个常数,那么复杂度实际上就是一个常数,不是吗?”答案是:不会。时间复杂度是对算法的时间执行随着输入的增长如何增长的“描述”。即使输入范围是[5, 35]
或[5, Integer.MAX_VALUE]
或[5, ∞)
,该“描述”仍然适用。这是运行时与输入大小之间的(相互)关系。
时间复杂度并不能告诉您算法将在什么时间运行。它告诉您更改输入大小对运行时的影响有多大。
让我们看看时间复杂度如何为您提供帮助:
时间复杂度是线性的。对于这么小的输入量,您可以得出一个合理的结论,即该算法是可行的,并且您不必为此担心太多。
但是,如果算法的时间复杂度例如为O(2^n)
,那么这将告诉您运行时将以很小的输入量爆炸,您将实际上必须查看尺寸35
是否仍然可以接受。