时间复杂度和二分查找法
一、时间复杂度
1、常数操作
操作和样本的数据量没有关系,每次都是固定时间内完成的操作。
2、时间复杂度
一个算法流程中,常数操作数量的一个指标。在表达式中,只要高阶项除去系数的部分,记为O(N^x)。
时间复杂度计算按照最坏情况进行。
评价一个算法的好坏,先看时间复杂度的指标,再分析不同数据样本下的实际运行时间,也就是“常数项时间”。
二、二分查找
时间复杂度O(logN)
应用
有序数组中判断数值是否存在
有序数组中找>=某个数最左侧的位置
局部最小
三、递归算法
int getMax(int arr[],int L,int R)
{
if(L==R)
{
return arr[L];
}
int mid=L+((R-L)>>1); //1、(L+R)可能溢出 2、位运算(R-L)>>1速度快于(R-L)/2
int leftMax=getMax(arr,L,mid);
int rightMax=getMax(arr,mid+1,R);
return max(leftMax,rightMax);
}
master公式(子问题等规模求解时间复杂度)
T(N)=a*T(N/b)+O(N^d)
a:子问题调用次数
b:子问题规模
O(N^d):其余时间复杂度
1)log(b,a)>d -> O(N^log(b,a))
2)log(b,a)<d -> O(N^d*logN)
3)log(b,a)=d -> O(N^d)
上述代码T(N)=2*T(N/2)+O(1)
四、对数器
有一个想测的方法a以及实现复杂度不好但是容易实现的方法b
实现一个随机样本产生器,用方法a和方法b跑相同的随机样本,观察结果是否一致
五、Qs
1)arr[]无序,任意俩相邻的数一定不相等,找出一个局部最小(arr[i]<arr[i-1]&&arr[i]<arr[i+1]),时间复杂度小于O(N)
若a[i]>a[i+1]&&a[j]<a[j+1]&&i<j,在a[i]至a[j+1]间进行二分查找
2)小和问题
一个数组中每个数左边比当前数小的数累加起来,叫做这个数组的小和。已知一个数组,求其小和
int smallSum(int arr[], int L, int R) //截取arr[L]~arr[R]部分
{
if (L == R) //防止无限递归
{
return 0;
}
int mid = L + ((R - L) >> 1);
return smallSum(arr, L, mid)+smallSum(arr,mid+1,R)+merge(arr,L,mid,R);
}
int merge(int arr[], int L, int M, int R)
{
int* temp = new int[R - L + 1];
int i = 0, p1 = L, p2 = M + 1;
int res=0;
while (p1 <= M && p2 <= R)
{
res+=arr[p1]<arr[p2]?(R-p2+1)*arr[p1]:0;
temp[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= M)
{
temp[i++] = arr[p1++];
}
while (p2 <= R)
{
temp[i++] = arr[p2++];
}
for (i = 0; i < R - L + 1; i++)
{
arr[L + i] = temp[i];
}
return res;
}