簡體   English   中英

嵌套在while循環中的for循環的時間復雜度是多少?

[英]What is the time complexity of this for loop nested in a while loop?

我正在嘗試優化功能。 我相信這個嵌套的for循環是二次的,但是我不是很肯定。 我重新創建了下面的功能

 const bucket = [["e","f"],[],["j"],[],["p","q"]] let totalLettersIWantBack = 4; //I'm starting at the end of the bucket function produceLetterArray(bucket, limit){ let result = []; let countOfLettersAccumulated = 0; let i = bucket.length - 1; while(i > 0){ if(bucket[i].length > 0){ bucket[i].forEach( (letter) =>{ if(countOfLettersAccumulated === totalLettersIWantBack){ return; } result.push(letter); countOfLettersAccumulated++; }) } i--; } return result; } console.log(produceLetterArray(bucket, totalLettersIWantBack)); 

這是解決此類問題的竅門 對於要分析其復雜度的代碼,假設沒有其他語句,只需寫出在最壞情況下執行每個語句所花費的時間。 請注意以#operations worst case:的注釋#operations worst case:

對於給定的代碼:

while(i > 0){ //#operations worst case: bucket.length
  if(bucket[i].length > 0){ //#operations worst case:: 1
    bucket[i].forEach( (letter) =>{  //#operations worst case: max(len(bucket[i])) for all i
    if(countOfLettersAccumulated === totalLettersIWantBack){ //#operations worst case:1
      return;
    }
    result.push(letter); //#operations worst case:1
   countOfLettersAccumulated++; //#operations worst case:1
    })
  }
  i--; ////#operations worst case:: 1
}

現在,我們可以將所有最壞情況的時間相乘( 因為在最壞情況下都可以實現,因此您始終可以設置totalLettersIWantBack = 10 ^ 9 )來獲取代碼段的O復雜度:

復雜度= O(bucket.length * 1 * max(len(bucket[i])) * 1 * 1 * 1 * 1)

= O(bucket.length * max(len(bucket[i]))

如果每個bucket [i]的長度為常數K ,那么您的復雜度將降低為: O(K * bucket.length ) = O(bucket.length)

請注意,隨着元素數量的增加,推送操作的復雜性可能不會保持恆定(最終,運行時將需要為添加的元素分配空間,並且可能必須移動所有現有元素)。

是否為平方取決於您認為N以及存儲桶的組織方式。 如果N是字母總數,則運行時受存儲桶中的bin數量(如果大於N)的約束,或者受存儲桶中的字母數量的約束(如果N較大)。 在任何一種情況下,搜索時間都隨着較大的邊界線性增加,如果一個將主​​導另一個,則時間復雜度為O(N)。 這實際上是一個帶有“轉彎”的線性搜索,壓縮線性搜索並將其隔開不會改變時間復雜度。 一段代碼中存在多個循環並不能單獨使它成為非線性。 再次以線性搜索為例。 我們搜索列表,直到找到最大的元素。

 //12 elements var array = [0,1,2,3,4,5,6,7,8,9,10,11]; var rows = 3; var cols = 4; var largest = -1; for(var i = 0; i < rows; ++i){ for(var j = 0; j < cols; ++j){ var checked = array[(i * cols) + j]; if (checked > largest){ largest = checked; } } } console.log("found largest number (eleven): " + largest.toString()); 

盡管使用了兩個循環而不是一個循環,但是運行時復雜度仍然是O(N),其中N是輸入中元素的數量。 將其縮減以使每個索引實際上是一個包含多個元素的數組,或者用空容器分隔相關元素不會改變運行時復雜度是線性限制的事實。

從技術上講,這是線性的,其中n是矩陣中元素總數。 這是因為,退出條件是的長度和在每個陣列你是否countOfLettersAccumulated等於totalLettersIWantBack。 不斷尋找價值。

如果您要尋找與矩陣尺寸匹配的答案,它將變得更加復雜,因為看起來的尺寸不是固定的。

您可以通過在存儲桶外的foreach處添加其他檢查,將這部分代碼變為常量,如果countOfLettersAccumulated等於totalLettersIWantBack,則您可以進行一次中斷。

我喜歡@axiom對復雜性分析的解釋

只是想添加可能的優化解決方案。

UPD .pushO(1) )比.concatO(n ^ 2) )快

這里也是測試數組推與concat

 const bucket = [["e","f"],[],["j", 'm', 'b'],[],["p","q"]] let totalLettersIWantBack = 4; //I'm starting at the end of the bucket function produceLetterArray(bucket, limit){ let result = []; for(let i = bucket.length-1; i > 0 && result.length < totalLettersIWantBack; i--){ //previous version //result = result.concat(bucket[i].slice(0, totalLettersIWantBack-result.length)); //faster version of merging array Array.prototype.push.apply(result, bucket[i].slice(0, totalLettersIWantBack-result.length)); } return result; } console.log(produceLetterArray(bucket, totalLettersIWantBack)); 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM