一、分治法
1.最大连续和
题意:给出一个长度为n的序列A1,A2,...An,求最大连续和。换句话说就是要求找到1<=i<=j<=n,使得Ai+Ai+1+...+Aj最大
代码:
int maxSum(int *A,int x,int y){//返回数组在左闭右开区间[x,y)中的最大连续和
int v,l,r,maxs;
if(y-x==1) return A[x]; //只有一个元素,直接返回
int m = x + (y-x)/2; //分治第一步,划分为[x,m)和[m,y)
maxs = max(maxSum(A,x,m),maxSum(A,m,y));//分治第二步:递归求解
v=0;l=A[m-1];
for(int i=m-1;i>=x;i--) l = max(l,v+=A[i]); // 分治第三步:合并(1)——从分界点开始往左的最大连续和L
v=0;r=A[m];
for(int i=m;i<y;i++) r = max(r,v+=A[i]);//分治第三步:合并(2)——从分界点往右的最大连续和R
return max(maxs,l+r);//把子问题的解L和R比较
}
2.归并排序
代码:
int cnt = 0;求逆序数
void merge_sort(int *A,int x,int y,int *T){
if(y-x>1){
int m = x + (y-x)/2;//划分
int p = x,q = m,i = x;
merge_sort(A,x,m,T); //递归求解
merge_sort(A,m,y,T); //递归求解
while(p<m||q<y){
if(q>=y||(p<m&&A[p]<=A[q]))
T[i++] = A[p++];//从左半数组复制到临时空间
else{
T[i++] = A[q++];//从右半数组复制到临时空间
cnt+=m-p;//这里“顺便”求逆序数
}
}
for(int i=x;i<y;i++) A[i]=T[i];//从辅助空间返回A数组
}
}
3.快速排序
代码:
void q_sort(int *a,int _left,int _right){
int i = _left ;
int j = _right;
int temp = a[_left];
if(_left>=_right) return;
while(i!=j){
while(i<j&&a[j]>temp)
j--;
if(j>i) a[i] = a[j];
while(i<j&&a[i]<=temp)
i++;
if(i<j) a[j] = a[i];
}
a[i] = temp;
q_sort(a,_left,i-1);
q_sort(a,i+1,_right);
}
4.二分查找
4.1 找一个数
代码:
void binarySearch(int num[],int len,int key)
{
int index1 = 0,index2 = len-1;
while(index1<=index2)
{
if(key==num[(index1+index2)/2])
{
cout<<"find"<<endl;
return;
}else if(key<num[(index1+index2)/2])
{
index2 = (index1+index2)/2 -1;
}else
{
index1 = (index1+index2)/2 +1;
}
cout<<index1<<" "<<index2<<endl;
}
cout<<"not found"<<endl;
}
4.2求一个数第一个出现的位置(lower_bound())
代码:
//这个算法中,first是最终要返回的位置
int lower_bound(int *array, int size, int key)
{
int first = 0, middle;
int half, len;
len = size;
while(len > 0) {
half = len >> 1;
middle = first + half;
if(array[middle] < key) {
first = middle + 1;
len = len-half-1; //在右边子序列中查找
}
else
len = half; //在左边子序列(包含middle)中查找
}
return first;
}
4.3求一个数最后出现的位置
代码:
int upper_bound(int *array, int size, int key)
{
int first = 0, len = size-1;
int half, middle;
while(len > 0){
half = len >> 1;
middle = first + half;
if(array[middle] > key) //中位数大于key,在包含last的左半边序列中查找。
len = half;
else{
first = middle + 1; //中位数小于等于key,在右半边序列中查找。
len = len - half - 1;
}
}
return first;
}