1、分析以下時間復雜度
void fun(int n)
{
int i=0,s=0;
while(s<n)
{
++i;
s=s+i;
}
}
分析:
n為規模,基本操作語句是++i
和s=s+i
,while循環處當s>=n不符合條件停止,假設執行m次結束,i=1,2,3..依次漸加,i只影響s值,主要看s, \(s_1\) =1, \(s_2\) =1+2=3, \(s_3\) =1+2+3=6,... \(s_m\) =1+2+3+...+m=m(m+1)/2 ,正解答案中給出,m(m+1)/2+k=n (k起修正作用的常數),也可大致口算m≈ \(\sqrt n\) ,則時間復雜度為O( \(\sqrt n\) )
2、設n為如下程序段處理的數據個數,求時間復雜度
for(i=1;i<n;i=2*i)
std::cout<<"i="<<i<<std::endl;
分析:
主看for
循環,當i>=n時結束,假設執行m次結束, \(i_1\) =2= \(2^1\) , \(i_2\) =2*2 = \(2^2\) , ..., \(i_m\) = \(2^m\) ,則有 \(2^m\) =n ,大致口算m= \(log_2 n\) ,則時間復雜度為O( \(log_2 n\) )
3、計算n!的遞歸函數如下,分析時間復雜度
int func(int n)
{
if(n<=1)
return 1; //①
else
return n*func(n-1); //②
}
分析:
n!遞歸函數中,①的時間復雜度顯然O(1),應主要分析else后的語句②,遞歸調用func(n-1)的時間開銷為T(n-1),則②時間開銷就是O(1)+T(n-1) 。
假設求1!就是O(1)+T(n-1)=1×O(1)+T(n-1)【n=1】 ,2!就是O(1)+O(1)+T(n-2)=2×O(1)+T(n-2)【n=2】... ,n!=(n-1)×O(1)+T(n-(n-1)) =(n-1)×O(1)+T(1) = n×O(1)=O(n) ,所以時間復雜度為O(n)
4、設A是一個線性表(a_1 ....a_n)采用順序存儲結構,則在等概率的前提下,平均插入一個元素需要移動的元素個數是多少?若元素插入在a_i(1≤i≤n)所在位置處的概率為 n-i/n(n-1)/2 ,則平均插入一個元素要移動的元素個數是多少?
分析:
(1):在a_1插入則要移動n次,a_2插入移動n-1次,...,a_n插入移動0次,總次數為0+1+2+...+n=n(n+1)/2 ,總共是0到n共1+n個 。則等概率下,平均插入一個元素移動的元素個數為[n(n+1)/2]/[1+n]=n/2
(2):將插入在a_i處插入概率用P表示,不難發現a_i處插入一個元素則需移動元素為n-i+1 ,可以以 {1,2,3,4,5}為例,在2處插入,5-2+1=4,故2,3,4,5四個元素往后移一位。則P概率下,平均插入一個元素移動的元素個數為 \(\sum P(n-i+1)\) = (2n+2)/3
5、設計一個算法,用不多於3n/2的平均比較次數,在數組A[0,...,n-1]中找出最大值和最小值的元素
//如果找最大值時遍歷一次,最小值時遍歷一次,則需要比較2n,所以盡量就遍歷一次
void MaxandMin(int A[],int n,int &max,int &min)
{
max=min=A[0];
for(int i=0;i<n;i++)
{
if(A[i]>max) max=A[i];
if(A[i]<min) min=A[i];
}
}
分析:
最壞情況是A中遞減次序排列,A[i]>max
均不成立,比較n-1次,同樣A[i]<min
同樣比較n-1次 ,總次數2(n-1)次,最好情況是A中遞增次序排列,A[i]>max
均成立,不執行A[i]<min
,總次數n-1 ,所以平均比較次數為[2(n-1)+(n-1) ]/2 = 3n/2-3/2 ,故符合題目條件。
6、分析以下程序時間復雜度
void fun()
{
int i=1,k=0,n=10;
while(i<=n-1)
{
k+=10*i;
++i;
}
}
分析:
顯然看出可以改寫為for(i=1;i<=n-1;++i)
,故時間復雜度為O(n)
void fun(int n)
{
int i=1,k=0;
do
{
k+=10*i;
++i;
}while(i==n)
}
分析:
顯然i!=n
時跳出循環,如:n=100,i=1,僅循環一次,故時間復雜度O(1)
void fun(n)
{
int i=1,j=0;
while(i+j<=n)
if(i>j)
++j;
else
++i;
}
分析:
可以寫幾個例子,1<=n i=1,j=1; 2<=n i=2,j=1 ;3<=n i=2,j=2 ... 顯然時間復雜度O(n)
void fun(int n)
{
int x=n,y=0;
while(x>=(y+1)*(y+1))
++y;
}
分析:
同樣寫幾個例子,x>=1×1 y=1 ; x>=2×2 y=2 ... 顯然時間復雜度O( \(\sqrt n\) )
void fun(n)
{
i=1;
while(i<=n)
i=i*2
}
分析:
同樣可以寫例子,顯然時間復雜度為O( \(log_2 n\) )
void fun(n)
{
i=1;
while(i<=n)
i=i*3
}
顯然時間復雜度為O( \(log_3 n\) )
7、假設n為2的乘冪,求以下時間復雜度
void counter()
{
int n,x,count;
std::cout<<"n:";
std::cin>>n;
count=0;
x=2;
while(x<n/2)
{
x=2*x;
++count;
}
std::cout<<count<<std::endl;
}
分析:
循環處x<n/2
,所以對x進行觀察,x= \(2^2\) , \(2^3\) ... 顯然時間復雜度為O( \(log_2 n\) )
8、某算法所需時間由以下方程表示,求出該算法時間復雜度(大O形式表達) 注意:n為求解問題規模,為簡單起見,設n為2的正整數冪
分析:
設n= \(2^m\) 則,
T(n)=T( \(2^m\) )=2T( \(2^m-1\) )+ \(2^m\)
=2(2T( \(2^m-2\) )+ $ 2^{m-1}$ )+ \(2^m\) = \(2^2\) ×T( \(2^{m-2}\) )+2× \(2^m\)
...
= \(2^m\) ×T(1)+m× \(2^m\)
= (m+1) \(2^m\)
= ( \(log_2 n\) +1 )n
=O(n \(log_2 n\))
9、分析sort函數時間復雜度
void sort(int j,int n)
{
int i,temp;
if(j<n)
{
for(i=j;i<=n;++i)
if(a[i]<a[j])
swap(a[i],a[j]); //本函數時間復雜度O(1)
++j;
sort(j,n) //遞歸調用
}
}
分析:
sort是一個遞歸排序過程,這里假設T(n) 是排序n各元素要的時間。縱觀代碼,主要花費時間在遞歸調用sort()
上。如果第一次調用,處理元素個數n-1,即對剩下n-1個元素進行排序,所需時間就是T(n-1) 。又sort()
在for
循環中,就需要n-1次比較。
列出方程:
T(1)=0 ,n=1
T(n)=T(n-1)+n-1 ,n>1
求解:
T(n)=[T(n-2)+(n-2)]+(n-1)
=[T(n-3)+(n-3)]+(n-2)+(n-1)
...
=(T(1)+1)+2+3+...+n-1
=0+1+2+...+n-1
=n(n-1)/2
=O(n²)
10、設計下列問題算法,分析其最壞情況的時間復雜度
(1)在數組A[0,...,n-1]中查找值為k的元素,若找到,則輸出其位置i(i為數組下標);否則輸出-1為坐標
int findK(int A[],int k) //這里假設A中元素都是int型
{
int i =0;
while(i<n&&A[i]!=k)
i++;
return i; //找到了
else
return -1;
}
最壞情況:就是遍歷一遍后查不到k,比較了n+1次,故時間復雜度O(n)
(2)在數組A[0,...,n-1]中找出元素的最大值和次最大值
void mxa(int A[],int M, int m) //M為最大值,m為次大值
{
int i;
M=m=MIN; //設MIN為已定義常量,比A[]中所有元素都小
for(i=0;i<n;i++)
{ //find M
if(A[i]>M) M=A[i];
}
for(i=0;i<n;i++)
{ //find m
if(A[i]!=M&&A[i]>m) m=A[i];
}
}
最壞情況:各來一次遍歷,並都是最后找到,一共比較了2n-2次,故時間復雜度O(n)