从给定数组中找出最大的两个数——二分递归

分析1:对于给定数组找出其中最大的两个数,很容易想到的就是遍历数组。首先遍历整个数组,找出最大的一个元素并记录下该位置;然后分别遍历该位置之前的区间和该位置之后的区间,分别找出这两个子区间的最大值,然后比较这两个子区间的最大值,大者即为整个数组的次大元素。显然,整个过程中,用到了三次for循环,算法的时间复杂度是比较大的,对于规模较小的数组尚且可以,但是当问题的规模非常大时,这种遍历的方法就不可行了。


分析2:设置两个指针,分别指向数组的最大值和次大值(初始化时指向数组的前两个元素)。此后遍历数组的所有元素,每个元素都与这两个指针所指元素进行比较,到最后就能确定最大值和次大值。但是复杂度与第一种方法不相上下。


分析3:递归+分治的方法。

递归:分别找出左右两个区间的最大值与次大值,然后通过比较这四个值的大小,确定整个数组的最大值与次大值。

递归基:区间元素为两个或三个的情况。

下面给出代码:

// 找出给定数组中最大的两个数

#include <iostream>
using namespace std;

void max2(int A[], int lo, int hi, int& x1, int& x2);
int main()
{
	int A[10] = {8, 3, 30, 25, 10, 22, 31, 35, 21, 19};
	int x1 = 0;
	int x2 = 0;
	max2(A, 0, 9, x1, x2);
	cout << "x1 = " << x1 << endl;
	cout << "x2 = " << x2 << endl;
	return 0;
}

void max2(int A[], int lo, int hi, int& x1, int& x2){
	//x1存放最大的一个元素,x2存放次大的元素
	
	//只有两个元素的情况
	if(lo + 1 == hi){
		if(A[lo] >= A[hi]){
			x1 = A[lo];
			x2 = A[hi];
			return;
		}
		else{
			x1 = A[hi];
			x2 = A[lo];
			return;
		}
	}
	
	//只有三个元素的情况
	if(lo + 2 == hi){
		if(A[lo] >= A[lo+1]){
			x1 =  A[lo];
			x2 = A[lo+1];
			if(A[hi] > x2)
				if(A[hi] > x1){
					x2 = x1;
					x1 = A[hi];
					return;
				}
				else{
					x2 = A[hi];
					return;
				}
		}
		else{
			x1 = A[lo+1];
			x2 = A[lo];
			if(A[hi] > x2)
				if(A[hi] > x1){
					x2 = x1;
					x1 = A[hi];
					return;
				}
				else{
					x1 = A[hi];
					return;
				}
		}
	}
	
	//有四个及以上的元素就可以通过分治递归的方式划分成上面两种情况
	int mi = (lo+hi) / 2;
	//分别计算左右两个区间的最大的两个数
	int x1L, x2L, x1R, x2R;
	max2(A, lo, mi, x1L, x2L);
	max2(A, mi+1, hi, x1R, x2R);
	
	if(x1L >= x1R){
		x1 = x1L;
		x2 = x2L > x1R ? x2L : x1R;
		return;
	}
	else{
		x1 = x1R;
		x2 = x1L > x2R ? x1L : x2R;
		return;
	}
}


  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值