分析下面的代码的时间复杂度,使用大O阶记法表示

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分析下面的代码的时间复杂度,使用大O阶记法表示相关的知识,希望对你有一定的参考价值。

常见的 查找算法的时间复杂度:
线性结构的查找的时间复杂度,如 二分查找(用于已经排好序的数据,如已序的数组);O(n)
非线性结构的查找的时间复杂度,如 二叉查找树 ;O(log n)

排序类别 时间复杂度 空间复杂度 稳定
1 插入排序 O(n2) O(1) √
2 希尔排序 O(n2) O(1) × //Shell(希尔)排序是基于插入排序的,时间效率比插入、选择、冒泡高,但又比快速排序低点;
3 冒泡排序 O(n2) O(1) √
4 选择排序 O(n2) O(1) ×
5 快速排序 O(Nlogn) O(logn) ×
6 堆排序 O(Nlogn) O(1) ×
7 归并排序 O(Nlogn) O(n) √

冒泡排序、插入排序、归并排序是稳定的,算法时间复杂度是O(n ^2);
选择排序、快速排序、堆排序、希尔排序都是 不稳定的;

算法的时间复杂度
一、 时间复杂度定义
定义:如果一个问题的规模是n,解这一问题的某一算法所需要的时间为T(n),它是n的某一函数T(n)称为这一算法的“时间复杂性”。
当输入量n逐渐加大时,时间复杂性的极限情形称为算法的“渐近时间复杂性”。

二、大O表示法
我们常用大O表示法表示时间复杂性,注意它是某一个算法的时间复杂性。大O表示只是说有上界,由定义如果f(n)=O(n),那显然成立f(n)=O(n^2),它给你一个上界,但并不是上确界,但人们在表示的时候一般都习惯表示前者。此外,一个问题本身也有它的复杂性,如果某个算法的复杂性到达了这个问题复杂性的下界,那就称这样的算法是最佳算法。

“大O记法" :在这种描述中使用的基本参数是n,即问题实例的规模,把复杂性或运行时间表达为n的函数。这里的“O”表示量级(order),比如说“二分检索是O(logn)的”,也就是说它需要“通过logn量级的步骤去检索一个规模为n的数组”记法O ( f(n) )表示当n增大时,运行时间至多将以正比于f(n)的速度增长。

这种渐进估计对算法的理论分析和大致比较是非常有价值的,但在实践中细节也可能造成差异。例如,一个低附加代价的O(n2)算法在n较小的情况下可能比一个高附加代价的O(nlogn)算法运行得更快。当然,随着n足够大以后,具有较慢上升函数的算法必然工作得更快。
O(1)
Temp=i;i=j;j=temp;
以上三条单个语句的频度均为1,该程序段的执行时间是一个与问题规模n无关的常数。算法的时间复杂度为常数阶,记作T(n)=O(1)。如果算法的执行时间不随着问题规模n的增加而增长,即使算法中有上千条语句,其执行时间也不过是一个较大的常数。此类算法的时间复杂度是O(1)。

O(n^2)
2.1.交换i和j的内容
sum=0; (一次)
for(i=1;i<=n;i++) (n次)
for(j=1;j<=n;j++)(n^2次)
sum++; (n^2次)
解:T(n)=2n^2+n+1 =O(n^2)追问

给我这个有什么用?我要的是答案,懂吗?

参考技术A O(1),常数阶的 参考技术B 输出就是f=5嘛追问

没学过计算机数据结构吗?

追答

没有,百度知道不适合专业问题╮( ̄⊿ ̄)╭

算法的时间复杂度

1.算法时间复杂度的定义

 

算法的时间复杂度,也就是算法的时间量度,记作:T(n)=O(f(n))。 它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间 复杂度,简称为-时间复杂度。其中f(n) 是问题规模n的某个函数。

这样用O()来体现算法时间复杂度的记法,我们称之为大O记法。一般情况,随着n的增大,T(n)增长最慢的算法为最优算法。

 

2.算法时间复杂度例子

 

2.1 常数阶

 

public class Agr {

    public static void main(String args[]) {
        //执行一次
        int m =1;
        //执行一次
        int n =2;
        //执行一次
        int mn = m*n;
        //执行一次
        System.out.println(mn);

    }

}

这个算法的运行次数是f(n)=4,依据推导方法,常数项全部变为1,那么这个算法的时间复杂度即为O(1)。事实上,这种与问题的多少(n的多少),执行恒定的算法,我们称之为O(1)的时间复杂度,简称常数阶。

 

2.2 线性阶

 

要确定某个算法的阶次,我们需要确定某个特定语句或某个语句运行的次数。因此,分析算法的时间复杂度,关键就是要分析循环结构的运行情况

public class Agr {

    public static void agrn(int n) {
        //循环n次
        for(int i=0;i<n;i++){
            System.out.println(n);
        }
    }

}

此段代码的时间复杂度即为O(n),因为循环体中的代码必须要执行n次。

 

2.3 对数阶

 

public class Agr {

    public static void agrn(int n) {
        //循环Log2 n次
        int count = 1;
        while (count < n) {
            count = count * 2;
            System.out.print(n);
        }
    }

}

由于每次count*2 ,离n更近一些,也就是有多少个2相乘后大于n,便退出循环。2x=n 得到 x=log2n。所以此循环的时间复杂度为O(logn)

 

2.4 平方阶

 

public class Agr {

    public static void agrn(int n) {

        //循环n次
        for (int i = 0; i < n; i++) {
            //循环n次
            for (int j = 0; j < n; j++) {
                System.out.println(n);
            }
        }
    }

}

此为一个循环嵌套算法,内外层循环皆为n,故总循环次数为n2,所以此算法时间复杂度为O(n2).

 

2.5 推导出的平方阶

 

public class Agr {

    public static void agrn(int n) {
        //循环n+n-1+n-2+....+1
        for (int i = 0; i < n; i++) {

            for (int j = i; j < n; j++) {
                System.out.println(n);
            }
        }
    }

}

由于内层嵌套循环中j=i, 当i=0时, 循环n次,i=1时,循环n-1 ... 以此类推,总的循环次数为 n + (n-1) + (n-2) + ...... + 1 = n(n+1)/2 = n2/2 + n/2 。这时候要用到大O阶的推导方法,没有加法常数不考虑,只保留最高项, 故还剩 n2/2,另外去掉此项相乘的常数1/2,最后这个算法的时间复杂度为O(n2).

 

3. 推导大O阶的方法总结

 

1.用常数1取代运行时间中的所有加法常数,无常数的不考虑。

2.只保留最高阶项。

3.最高阶项存在且不是1,那么去掉与此项相乘的常数。

按照此3项方法,推导出来的结果,即大O阶。

 

4. 常见算法时间复杂度所消耗时间的大小排列

 

O(1) < O(logn)<O(n)<O(n2)

 

5. 最坏情况

 

当我们在查找n个随机数字数组中的某个数字,最好的情况是第一个数字就是,时间复杂度为O(1),最坏的情况遍历完整个数组才找到,时间复杂度为O(n)。 除非特别说明,我们一般指的运行时间,都是最坏情况下的运行时间,时间复杂度也是最坏情况下的时间复杂度。

 


以上是关于分析下面的代码的时间复杂度,使用大O阶记法表示的主要内容,如果未能解决你的问题,请参考以下文章

算法分析 - 基础

渐进记法(O,Ω,Θ)

大O记法

Web高级 JavaScript中的数据结构

第八周学习

算法的时间复杂度