同时找到最大值和最小值——编程之美
给定一个数组,我们可以同时找到其中的最大数和最小数吗?要求时间复杂度尽可能的小。
编程之美上面提供了三个思路,我把它们都实现了,并做一些讲解补充。
思路一:
两次遍历,分别得到最大值和最小值。时间复杂度为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; }
时间: 2024-11-07 20:49:02