時間復雜度十道練習題目


1、分析以下時間復雜度

void fun(int n)
{
    int i=0,s=0;
    while(s<n)
    {
        ++i;
        s=s+i;
    }
}

分析:

n為規模,基本操作語句是++is=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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM