时间复杂度与常见排列算法

一、时间复杂度概念

1、时间复杂度概念

提到时间复杂度,第一时间想到的是算法,简单说,算法就是你解决问题的方法,而你用这个方法解决这个问题所执行的语句次数,称为语句频度或者时间频度,记为T(n)。

什么是时间复杂度,算法中某个函数有n次基本操作重复执行,用T(n)表示。
现在有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。
记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。
通俗一点讲,其实所谓的时间复杂度,就是找了一个同样曲线类型的函数f(n)来表示这个算法的在n不断变大时的趋势 。
当输入量n逐渐加大时,时间复杂性的极限情形称为算法的“渐近时间复杂性”。

2、计算时间复杂度的方法:

推导大O阶,我们可以按照如下的规则来进行推导,得到的结果就是大O表示法:
a.用常数1来取代运行时间中所有加法常数。
b.修改后的运行次数函数中,只保留最高阶项
c.如果最高阶项存在且不是1,则去除与这个项相乘的常数。

二、理解

1、常数阶:O(1)的算法是一些运算次数为常数的算法。例如:

    temp=a;
    a=b;
    b=temp;

上面语句共三条操作,单条操作的频度为1,即使他有成千上万条操作,也只是个较大常数,这一类的时间复杂度为O(1)。

int sum = 0,n = 100; //执行一次  
sum = (1+n)*n/2; //执行一次  
System.out.println (sum); //执行一次 

上面算法的运行的次数的函数为f(n)=3,根据推导大O阶的规则1,我们需要将常数3改为1,则这个算法的时间复杂度为O(1)。

2、线性阶:O(n)的算法是一些线性算法。例如:

    sum=0for(i=0;i<n;i++)      
        sum++;

上面代码中第一行频度1,第二行频度为n,第三行频度为n,所以f(n)=n+n+1=2n+1。所以时间复杂度O(n)。这一类算法中操作次数和n正比线性增长。

3、对数阶:O(logn) 一个算法如果能在每个步骤去掉一半数据元素,如二分检索,通常它就取 O(logn)时间。例如:

    int i=1; 
    while (i<=n) 
        i=i*2; 

上面代码设第三行的频度是f(n), 则:2^f(n)<=n;f(n)<=log₂n,取最大值f(n)= log₂n,所以T(n)=O(log₂n ) 。

4、平方阶:O(n²)(n的k次方的情况)最常见的就是平时的对数组进行排序的各种简单算法都是O(n²),例如直接插入排序的算法。

    sum=0for(i=0;i<n;i++)  
        for(j=0;j<n;j++) 
          sum++;

第一行频度1,第二行n,第三行n²,第四行n²,T(n)=2n²+n+1 =O(n²)

5、平方阶:O(n²)

for(int i = 0; i < n; i++){
    for(int j = i; j < n; j++){
        printf("%d ",i);
    }
}  
//运行次数为(1+n)*n/2
//时间复杂度O(n^2)

6、时间复杂度按n越大算法越复杂来排的话:

常数阶O(1)、对数阶O(logn)、线性阶O(n)、线性对数阶O(nlogn)、平方阶O(n²)、立方阶O(n³)、……k次方阶O(n的k次方)、指数阶O(2的n次方)。

O(1)<O(logn)<O(n)<O(nlogn)<O(n²)<O(n³)<O(2ⁿ)<O(n!)

三、其他

1、冒泡程序—平方阶

public void sort(int[] args)
{
    //第一层循环从数组的最后往前遍历
    for (int i = args.length - 1; i > 0 ; --i) {
        for (int j = 0; j < i; j++) {
            //保证在相邻的两个数中比较选出最大的并且进行交换(冒泡过程)
            if (args[j] > args[j+1]) {
                int temp = args[j];
                args[j] = args[j+1];
                args[j+1] = temp;
            }
        }
    }
}

上面算法的运行的次数函数为f(n)= (n-1)+(n-2)+(n-3)+(n-4)+…===>等差数列求和===> (n*(n-1))/2 ===>n^2/2-n/2===> f(n)=O(n^2)

2、选择排序

public void sort(int[] args)
{
    int len = args.length;
    for (int i = 0,k = 0; i < len; i++,k = i) {    n
        // 在这一层循环中找最小
        for (int j = i + 1; j < len; j++) {    n-1
            // 如果后面的元素比前面的小,那么就交换下标,每一趟都会选择出来一个最小值的下标
            if (args[k] > args[j]) k = j;
        }

        if (i != k) {
            int tmp = args[i];
            args[i] = args[k];
            args[k] = tmp;
        }
    }
}

上面算法的运行的次数函数为f(n)= (n-1)+(n-2)+(n-3)+(n-4)+…===>等差数列求和===> (n*(n-1))/2 ===>n^2/2-n/2===> f(n)=O(n^2)

3、插入排序

public static void insertSort(int a[]){
    int fn = 0;
    int n = a.length;
    int temp = 0;
    printfArray(a);
    for(int i = 1; i < n; i++){
        for(int j = i; j >0; j--){
            fn++;
            if(a[j] < a[j-1]){ // 交换
                temp = a[j];
                a[j] = a[j-1];
                a[j-1] = temp;
            }else{
                break;
            }
        }
        printfArray(a);
    }
    printfArray(a);
    System.out.println("语句频度:"+fn);
}

上面算法的运行的次数函数为f(n)= (n-1)+(n-2)+(n-3)+(n-4)+…===>等差数列求和===> (n*(n-1))/2 ===>n^2/2-n/2===> f(n)=O(n^2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值