1 题目描述
下列程序段的时间复杂度是
int sum = 0;
for(int i = 1; i < n; i *= 2)
for(int j = 0; j < i; j++)
sum++;
2 思路
观察程序,可以发现内层的执行次数和外层的执行次数一致,内层与外层是“捆绑”关系,简言之,外层执行一次,内层执行 i 次。所以最后结果取内层的时间复杂度即可。
整体思路就是,先求出外层的执行次数,然后代到内层中,计算出最后的时间复杂度。
3 解答
法一
首先回忆一下等比数列求和公式:
S = a 1 1 − q n 1 − q S=a_1\frac{1-q^n}{1-q} S=a11−q1−qn其中a1
代表首项,q
代表公比,n
为项数。
回到本题,先观察最外层的for
循环,i
的变化趋势为(其中k
表示为第k
次执行):
1 , 2 , 4 , 8 , . . . , 2 k − 1 1,2,4,8,...,2^{k-1} 1,2,4,8,...,2k−1粗略求得外层的执行次数:
2 k − 1 = n 2^{k-1}=n 2k−1=n k − 1 = l o g 2 n k-1=log_2n k−1=log2n k = l o g 2 n + 1 k=log_2n+1 k=log2n+1 ≈ l o g 2 n ≈log_2n ≈log2n
接下来求内层时间复杂度,由于内层的执行次数和外层的循环变量i
执行次数一致,于是可以得出内层循环执行次数的变化趋势: 1 , 2 , 4 , 8 , . . . , l o g 2 n 1,2,4,8,...,log_2n 1,2,4,8,...,log2n显然首项为1
,公比为2
,一共 l o g 2 n log_2n log2n项,代入等比数列求和公式得: 1 ⋅ 1 − 2 l o g 2 n 1 − 2 1·\frac{1-2^{log_2n}}{1-2} 1⋅1−21−2log2n = 1 − n − 1 =\frac{1-n}{-1} =−11−n → O ( n ) →O(n) →O(n)
法二
参考法一,内层的j
最大值等于i
的最大值,即 2 k − 1 2^{k-1} 2k−1,外层最多执行到 l o g 2 n log_2n log2n次[k
是执行的次数],写出公式:
∑ k = 0 l o g 2 n ∑ j = 0 2 k − 1 1 = ∑ k = 0 l o g 2 n 2 k + 1 = 1 − 2 l o g 2 ( n + 1 ) 1 − 2 = n + 1 − 1 \sum_{k=0}^{log_2{n}}\sum_{j=0}^{2^{k-1}}1=\sum_{k=0}^{log_2{n}}2^{k+1}=\frac{1-2^{log_2({n+1)}}}{1-2}=n+1-1 k=0∑log2nj=0∑2k−11=k=0∑log2n2k+1=1−21−2log2(n+1)=n+1−1 = O ( n ) =O(n) =O(n)
总结
简单来说,这道题也可以这么想:
i=1,执行1次,
i=2,执行2次,
i=4,执行4次,
I=8,执行8次,
…
i=2的k次方,说明共执行2的k次方次;
等比数列求和求出结果,即为最终的时间复杂度
内容仅供参考,如有错误请指出,谢谢!