我在网站www.interviewcake.com上有此代码,该网站称该代码为O(n),并且在面试蛋糕上要求团队成员进行澄清后,他们确认这是正确的。这是代码:
function reverseWords(message) {
// First we reverse all the characters in the entire message
reverseCharacters(message, 0, message.length - 1);
// This gives us the right word order
// but with each word backward
// Now we'll make the words forward again
// by reversing each word's characters
// We hold the index of the *start* of the current word
// as we look for the *end* of the current word
let currentWordStartIndex = 0;
for (let i = 0; i <= message.length; i++) {
// Found the end of the current word!
if (i === message.length || message[i] === ' ') {
// If we haven't exhausted the string our
// next word's start is one character ahead
reverseCharacters(message, currentWordStartIndex, i - 1);
currentWordStartIndex = i + 1;
}
}
}
function reverseCharacters(message, leftIndex, rightIndex) {
// Walk towards the middle, from both sides
while (leftIndex < rightIndex) {
// Swap the left char and right char
const temp = message[leftIndex];
message[leftIndex] = message[rightIndex];
message[rightIndex] = temp;
leftIndex++;
rightIndex--;
}
}
面试蛋糕上的团队成员说:
*是的,有一个嵌套循环,看起来像是O(n ^ 2)。
但是,在问题过程中,我们可以看到我们没有在每个内部循环中反转O(n)个字符……我们仅将每个字符精确地反转了两次。因此,总成本最终为O(n)。
这是一个棘手的问题,因为您必须查看整个算法中所有对reverseCharacters的调用的开销,而不是每个调用本身的开销。*
不过,我仍然感到困惑,因为我们仍在内部循环中循环遍历EACH字符,并且字符串越大,则运行调用所花费的时间就越长。
我想将其开放给其他渠道,以查看是否可以对此获得更多了解,以及为什么使用O(n)而不是O(n)^ 2。
要完全清楚,我想解释一下为什么上面提供的代码中的reverseWords
函数是O(n)而不是O(n)^ 2
答案 0 :(得分:3)
根据我在该代码中看到的内容,外循环的工作是查找每个单词的结尾。一旦找到(并且只有这样),将调用reverseCharacters()
来反转该单词中的字符。因此,两个任务中的大O相加(O(n)+ O(n)= O(2n),但仍视为O(n)),而不是相乘(O(n)* O (n)= O(n ^ 2)),就像您通常希望它们在嵌套循环中那样。
答案 1 :(得分:0)
这确实是O(n)
。
造成混淆的原因是在内部循环中调用了reverseCharacters()
。但是,请注意何时调用。
让我们看一下字符串中的任意字符,看看它多久被“触摸”了。
让我们的角色在i
的索引上i
。
reverseCharacters()
在输入字符串中的每个单词被调用一次。字符i
仅出现在一个单词中。
这意味着该代码的实际复杂度为:
T(n) = O(n // First reverseCharacters()
+ n // looping through all characters
+ l1 // reverseCharacters() on the first word
+ l2 // reverseCharacters() on the second word
+ ... // and so on ...
+ lk) // reverseCharacters() on the k'th (and last) word.
自l1 + l2 + ... + lk <= n
起,这意味着我们拥有:
T(n) = O(n + n + l1 + l2 + ... + lk) <= O(n + n + n) = O(n)