分治法需要对分解的子问题分别求解,再对子问题进行合并,减治法只对一个子问题求解,并且不需要进行解的合并。减治法的效率更好。
*时间复杂性为log2n
*思路:如果n=1,返回a的值;n是偶数且n>1,把该问题的规模减半,计算a^n/2的值;n是奇数且n>1,先利用偶指数的规则计算a^(n-1),再把结果乘以a
a n=1
a^n= (a^n/2)^2 n>1且n是偶数
(a^n-1/2)^2*a n>1且n是奇数
例题
减治法求两个序列的中位数
#include<iostream>
using namespace std;
int SearchMid(int A[],int B[],int n){
//初始化两个序列的上下界
int s1=0,e1=n-1,s2=0,e2=n-1;
int mid1,mid2;
while(s1<e1&&s2<e2){ //循环--直到区间只有一个元素
mid1=(s1+e1)/2; //序列A的中位数下标
mid2=(s2+e2)/2; //序列B的中位数下标
if(A[mid1]==B[mid2]){ //当a=b时 返回a 算法结束
return A[mid1];
}
if(A[mid1]<B[mid2]){ //a<b 舍弃a之前的元素舍弃b之后的元素 (a,b)之间
if((s1+e1)%2==0) s1=mid1; //头指针变成mid开始
else s1=mid1+1;
e2=mid2; //尾指针变成中间部分
}
if(A[mid1]>B[mid2]){ //a>b 舍弃a之后的元素舍弃b之前的元素(b,a)之间
if((s2+e2)%2==0) s2=mid2;
else s2=mid2+1;
e1=mid1;
}
}
//返回较小者
if(A[s1]<B[s2]){
return A[s1];
}
else{
return B[s2];
}
}
int main(){
int n; //长度
cout<<"请输入数组长度:"<<endl;
cin>>n;
int A[n],B[n];
cout<<"请输入A数组:"<<endl;
for(int i=0;i<n;i++){
cin>>A[i];
}
cout<<"请输入B数组:"<<endl;
for(int i=0;i<n;i++){
cin>>B[i];
}
int res=0;
res=SearchMid(A,B,n);
cout<<"中位数是:"<<res<<endl;
return 0;
}
查找问题
折半查找
折半查找与待查值每比较依次,根据比较结果是的查找的区间减半
*前提:序列有序,若序列无序,需要先进行排序
#include<iostream>
using namespace std;
int BinSearch(int r[],int n,int k){
int low=0,high=n-1;
int mid;
while(low<=high){
mid=(low+high)/2;
if(k<r[mid]){
high=mid-1;
}
else if(k>r[mid]){
high=mid+1;
}
else{
return mid;
}
}
return -1; //查找失败,返回-1
}
int main(){
int n;
c