算法学习(二)时间复杂度

一、时间复杂度分析

1、什么是大O

  1. O(f(n))表示运行算法所需要执行的指令数,和f(n)成正比
  • 二分查找法O(longn)   所需执行指令数: a*longn
  • 寻找数组中最大/最小值O(n)   所需执行指令数 :b*n
  • 归并排序O(nlogn)   所需指令数:c*nlogn
  • 选择排序O(n^2)   所需指令数:d*n^21

从图中可以看出来n的差距是量级上的差距,可以看出来前面的常数可以忽略不计

 

 

 

不同复杂度的函数

  1. 在学术上来讲O(f(n))表示算法执行的上界
    归并排序复杂度是O(nlogn)的,但同时也是O(n^2)的,因为O表示时间的上界,这个算法真正执行的指令数可能是cnlogn 可能<= an^2的
    但是业界就用O表示算法的执行最低上界
    一般不会说归并排序是O(n^2)的
  2. 一个算法有多个部分组成,复杂度取最大的(前提是对应的n数量级是差不多的)
  • O(nlogn+n)=O(nlogn)
  • O(nlogn+n2)=O(n2)

如果O(AlongA+B) ,O(AlogA+B^2),这样的就不行

 

二、对数据规模的概念

1、如果想在1s内解决问题:

O(n2)的算法可以处理大约104级别的数据
O(n)的算法可以处理大约10^8级别的数据
O(nlogn) 的算法可以处理大约10^7级别的数据

2、空间复杂度

多开一个辅助数组:O(n)
多开一个辅助二维数组:O(n^2)
多开常数空间:O(1)
递归调用是有空间代价的

三、常见的复杂度分析

  • O(1)
void swap(int &a ,int &b){
    int temp=a;
    a=b;
    b=temp;
}
  • O(n),典型的特征是存在一个循环,循环次数是c*n次
//反转字符串
void reverse(string &s){
    int n=s.size();
    for(int i=0;i<n/2;i++)
          swap(s[i],s[n-1-i]);
}
  • O(n^2),双重循环
  • O(logn)
//二分查找
int binarySearch(int arr[],int n,int target){
    int l=0,r=n-1;
    while(l<=r){
        int mid=l+(r-l)/2;
        if(arr[mid]==target)
            return mid;
        if(arr[mid]>target){
            r=mid-1;
        }else{
            l=mid+1;
        }
    }
    return -1;
}

 

 

  • O(sqrt(n))
//判断是不是质数
bool isPrime(int n){
    for(int x=2;x*x<=n;x++){
        if(n%x==0)
            return false;
    return true;
}

四、递归调用复杂度

//递归的二分查找
int binarySearch(int arr[],int l,int r,int traget){
    if(l>r)
        return -1;
    int mid=l+(r-l)/2;
    if(arr[mid]==target){
        return mid;
    }else if(arr[mid]>target){
        return binarySearch(arr,l,mid-1,target);
    }else{
        return binarySearch(arr,mid+1,r,target);
    }
}   
  • 这个算法递归的深度为O(logn),处理问题的复杂度是O(1),所以时间复杂度也是O(logn)
  • 递归的时间复杂度:如果递归函数中,只进行一次递归调用,递归深度为depth,在每个递归函数中,时间复杂度为T,则总体时间复杂度为O(T*depth)
  • 如果2次递归调用,如下面函数,分析复杂度应该计算调用次数

     

     

  • 归并,快速排序等事件复杂度不是O(2^n)而是O(nlogn),因为再上一个例子中树的深度是n,而在这些排序算法中树的深度是logn,在这些排序算法中每个节点处理的数据规模是逐渐缩小的,而上一个例子每个节点处理的数据规模是一样的。

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值