[英]How is the time complexity O(n) and not O(n^2)?
我正在LeetCode.com上解決一個問題:
給定一個由正整數組成的向量
nums
,計算並打印子數組中所有元素的乘積小於k的(連續)子數組的數量。
代碼(我在大量在線幫助下編寫的)如下:
class Solution {
public:
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
if(nums.empty() || k<=1) return 0;
int counter=0, left=0, currProd=1;
for(int i=0; i<nums.size(); i++) {
currProd*=nums[i];
while(left<nums.size() && currProd>=k)
currProd/=nums[left++];
counter+=i-left+1;
}
return counter;
}
};
雖然我了解發生了什么,但我不明白時間復雜度如何稱為O(n)
而不是O(n^2)
。 恕我直言, i
和left
都會增加,導致在最壞的情況下兩次訪問nums
每個元素-一次通過歸納變量i
然后再一次通過left
。
那么,時間復雜度O(n)
如何?
盡管代碼看起來像是O(N^2)
-,但要注意的關鍵是:
在for循環中,
left
永遠不會重置為0,並且在while循環中始終會遞增。
這意味着while
循環在整個代碼執行期間最多只能執行N
次。 因此,代碼僅在數組中運行兩次,即O(N)
。
每次執行內循環體時, left
遞增1 left
是最初為0和從未增長超過nums.size()
因此,內部循環的主體最多執行nums.size()
次。
外循環的主體將被精確執行nums.size()
次。
因此,函數的執行時間最多為T0 + nums.size() * T1 + nums.size() * T2
,其中T0是在外循環之外執行代碼所需的時間,T1是執行外部循環所需的時間。執行一次不包括內循環的外循環迭代,T2是執行內循環的一次迭代所需的時間。 此上限的形式為A + nums.size() * B
,其中A和B是一些常量。 因此,函數的執行時間為O(nums.size())
。
當您有兩個嵌套循環時,整個程序的復雜度最多為 M*N
,其中M
是外循環的迭代次數, N
是內循環的最大迭代次數。 因此,程序的復雜度滿足O(M*N)
。 有時可能會找到下界,因為內部循環的迭代次數會有所不同。 在這里,有一個不變量保證內部循環最多執行一定次數的總次數,這比O(nums.size() * nums.size())
綁定更好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.