要求比较次数小于2n。
最直接的做法,比较次数为2n:
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
vector<int> a(n);
for(int i = 0; i < n; ++i) cin >> a[i];
int min_val = a[0], max_val = a[0];
for(int i = 1; i < n; ++i){
if(a[i] > max_val) max_val = a[i];
if(a[i] < min_val) min_val = a[i];
}
cout << min_val << " " << max_val << endl;
return 0;
}
如果要减少比较次数,应该怎么做呢?
当某个元素比较大元素大的时候,就不必再与较小元素比较了:
int main(){
int n;
cin >> n;
vector<int> a(n);
for(int i = 0; i < n; ++i) cin >> a[i];
int min_val = a[0], max_val = a[0];
for(int i = 1; i < n; ++i){
if(a[i] > max_val) max_val = a[i];
else if(a[i] < min_val) min_val = a[i];
}
cout << min_val << " " << max_val << endl;
return 0;
}
这样比较次数就会小于2n。那还有更好的方法吗?
可以分治:先让相邻的两个数进行比较,较大者放在右边(奇数下标),较小者放在左边(偶数下标),比较次数n/2。这样全局的最大值肯定在偶数下标,最小值肯定在奇数下标,分别寻找最值,比较次数为n/2 + n/2 = n,所以最终比较次数1.5n。
int main(){
int n;
cin >> n;
vector<int> a(n);
for(int i = 0; i < n; ++i) cin >> a[i];
for(int i = 0; i < n-1; i += 2){//分治处理,较大者放右边
if(a[i] > a[i+1]) swap(a[i], a[i+1]);
}
int min_val = a[0];
for(int i = 2; i < n; i += 2){
if(a[i] < min_val) min_val = a[i];
}
int max_val = a[1];
for(int i = 3; i < n; i += 2){
if(a[i] > max_val) max_val = a[i];
}
if(n%2){//如果存在最后一个单独的元素
min_val = min(min_val, a[n-1]);
max_val = max(max_val, a[n-1]);
}
cout << min_val << " " << max_val << endl;
return 0;
}
这种题你说它难吧,也不难,思想很简单,但是就是不一定能想出来,很巧