同时找到最大值和最小值——编程之美

同时找到最大值和最小值——编程之美

    

    给定一个数组,我们可以同时找到其中的最大数和最小数吗?要求时间复杂度尽可能的小。


编程之美上面提供了三个思路,我把它们都实现了,并做一些讲解补充。


    思路一:


两次遍历,分别得到最大值和最小值。时间复杂度为O(2*N)。


    思路二:


把最前面的两个数作为最值的候选,然后后面的数两两一组,分别让其中的较大值和候选最值比较,让其中的较小值和候选最值比较。

    感觉这种方法和推排序有点儿类似。。


    思路三:


采用分治法思想,把整个数组一分为二,让左边的最值和右边的最值分别比较,这里有个递归的过程,主要跳出递归的条件是当数组的begin和end相差小于等于1的时候,跳出。


    上面三个思路的代码如下:


#include<iostream>
using namespace std; 

struct Pair
{
	int max, min; 
};

// 遍历两次,时间复杂度为O(2*N)
Pair minMax_1(int a[], int n)
{
	int max = a[0], min = a[0]; 

	for(int i = 0; i < n; i++)
	{
		min = a[i] < min ? a[i]:min; 
		max = a[i] > max ? a[i]:max; 
	}

	Pair p; 
	p.max = max; 
	p.min = min; 

	return p; 
}

// 两两比较,时间复杂度是O(1.5*N)
Pair minMax_2(int a[], int n)
{
	int max = a[0], min = a[1]; 
	if(max < min)
		swap(max, min); 

	for(int i = 2; i < n; i = i + 2)  // 递进2个
	{
		int tmpMin = a[i]; 
		int tmpMax = a[i+1]; 
		if(tmpMax < tmpMin)
			swap(tmpMin, tmpMax);   // 候选

		max = max > tmpMax ? max:tmpMax; 
		min = min < tmpMin ? min:tmpMin; 
	}

	// 防止长度为奇数
	max = max > a[n-1] ? max:a[n-1]; 
	min = min < a[n-1] ? min:a[n-1]; 	

	Pair p; 
	p.max = max; 
	p.min = min; 

	return p; 
}

// 分治法,时间复杂度也是O(1.5*N)
Pair minMax_3(int a[], int begin, int end)
{
	Pair P; 
	if(end - begin <= 1)
	{
		P.max = a[begin] > a[end] ? a[begin]:a[end]; 
		P.min = a[begin] < a[end] ? a[begin]:a[end]; 
		return P; 
	}

	Pair PL = minMax_3(a, begin, begin + (end - begin) / 2); 
	Pair PR = minMax_3(a, begin + (end - begin) / 2 + 1, end); 
	P.max = PL.max > PR.max ? PL.max:PR.max; 
	P.min = PL.min < PR.min ? PL.min:PR.min; 

	return P; 
}

int main()
{
	Pair P; 
	int a[] = {3, 6, 1, 8, 0}; 
	int n = 5; 

	// solution 1 
	P = minMax_1(a, n); 
	cout<<P.min<<' '<<P.max<<endl; 

	//solution 2
	P = minMax_2(a, n); 
	cout<<P.min<<' '<<P.max<<endl; 

	//solution 3
	P = minMax_3(a, 0, n-1); 
	cout<<P.min<<' '<<P.max<<endl; 

	return 0; 
}



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值