减治法(引例中位数、查找问题:折半&二叉&选择、排序问题:堆排序、组合问题:淘汰赛冠军问题&假币问题)

分治法需要对分解的子问题分别求解,再对子问题进行合并,减治法只对一个子问题求解,并且不需要进行解的合并。减治法的效率更好。

*时间复杂性为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
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值