简体   繁体   English

该函数的时间复杂度是O(N)还是O(N ^ 2)?

[英]Is the time complexity for this function O(N) or O(N^2)?

I am trying to determine the time complexity for the following function. 我试图确定以下功能的时间复杂度。

The function reverses the order of words in a string and then reverses the order of letters in a word. 该函数反转字符串中单词的顺序,然后反转单词中字母的顺序。

For example: 例如:

“the sky is blue” => “eulb si yks eht” “天空是蓝色的”=>“eulb si yks eht”

var reverseString = function(s) {
  let str = s.split(' ')
  let word;
  let wordRev;
  let result = [];
  let countI = 0
  let countJ = 0    

  //lets call this loop "i"
  for(let i=str.length-1; i>=0; i--) {
    word = str[i]
    wordRev = ""
    countI +=1

    //lets call this loop "j"      
    for(let j=word.length-1; j>=0; j--) {
      wordRev += word[j]
      countJ+=1
    }
    result.push(wordRev)
  }
  return result.join(" ")
};

Although there are two nested loops, I believe the time complexity is O(n) and I will give two scenarios as an example. 虽然有两个嵌套循环,但我相信时间复杂度为O(n),我将以两个场景为例。

•     Scenario 1:
   ⁃    s.length: 22
   ⁃    input: “thisisreallylongstring”
   ⁃    str: [“thisisreallylongstring”]
   ⁃    i loop count total: 1
   ⁃    j loop count total: 22
•   Scenario 2
   ⁃    s.length = 11
   ⁃    input: “s t r i n g”
   ⁃    str: [“s”, “t”, “r”, “i”, “n”, “g”]
   ⁃    j loop count total: 6
   ⁃    i loop count total: 6

The count total of loops i and j are roughly equal to the length on the input, which leads me to believe that even though there are two nested loops it is still O(n) complexity. 循环i和j的计数总数大致等于输入的长度,这使我相信即使有两个嵌套循环,它仍然是O(n)复杂度。

Am i wrong in my line of thinking? 我的想法是错的吗?

Two factors are at play here: 这里有两个因素:

  1. Your algorithm itself is O(n). 你的算法本身就是O(n)。 The substrings processed in each inner loop are disjoint. 在每个内循环中处理的子串是不相交的。 That is, you have two nested loops, but the part of the string processed in the inner loop is never repeated by separate iterations in the outer loop. 也就是说,您有两个嵌套循环,但在内部循环中处理的字符串部分永远不会通过外部循环中的单独迭代重复。 Each inner loop gets its own separate substring, and when you add them together, it's O(n). 每个内部循环都有自己独立的子字符串,当你将它们加在一起时,它就是O(n)。

  2. Appending strings this way makes the algorithm O(n^2). 以这种方式附加字符串使得算法O(n ^ 2)。 Strings are immutable so each call to wordRev += word[j] will create a brand new string. 字符串是不可变的,因此每次调用wordRev += word[j]都会创建一个全新的字符串。 In the worst case, such as for "thisisreallylongstring" , you end up creating "g", "gn", "gni", ... as intermediate strings. 在最坏的情况下,例如"thisisreallylongstring" ,你最终创建"g", "gn", "gni", ...作为中间字符串。 Adding them together, it's O(n^2). 将它们加在一起,就是O(n ^ 2)。

So the overall answer is O(n^2). 所以整体答案是O(n ^ 2)。

All you really care about is how many times the inner loop runs and if everything you are doing in the loops is constant time. 你真正关心的是内循环运行的次数,以及你在循环中所做的一切是不变的时间。 In your case the inner loop always runs n times where n is the number of letters in your sentence. 在你的情况下,内部循环总是运行n次,其中n是句子中的字母数。 For testing you can make some fake sentences easily and actually count how many times the loop runs. 对于测试,您可以轻松地制作一些假句子并实际计算循环运行的次数。 So with a sentence made with: let str = Array.from({length: 20}, ()=>'a'.repeat(20)).join(' ') you'll find the inner loop runs exactly 400 times. 所以使用以下句子: let str = Array.from({length: 20}, ()=>'a'.repeat(20)).join(' ')你会发现内循环运行正好400次。 Which is exactly how many letters you have. 这正是你有多少封信。 You sometimes need to be careful with the javascript functions because they don't always run in constant time — for example if you where splicing arrays in the loops, but you don't appear to be doing that here. 你有时需要小心javascript函数,因为它们并不总是在恒定的时间内运行 - 例如,如果你在循环中拼接数组,但你似乎没有这样做。 Everything should run in linear time. 一切都应该在线性时间内运行。 So O(n) where n is the number of letters. 所以O(n)其中n是字母数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM