题目描述
给一个 n 个数字的顺序表,求其中的最大值和最小值。求一个比较次数不大于 ⌈ 3 n / 2 ⌉ − 2 \lceil 3n/2 \rceil-2 ⌈3n/2⌉−2 的算法。
思路
顺序查找
首先最大、最小值初始化为第一个数,对于之后的数我们都进行比较更新。易得最坏情况下比较次数为 2 n − 3 2n-3 2n−3 。实现见代码 f0 部分。
分组比较
我们可以预处理数组:每两个数字划成一组,较小的放前面,较大的放后面。于是,最小值就可以从前面的数字中获取,最大值从后面的数字获取。比较次数计算如下:
复杂度符合要求。实现见代码 f2 部分。
递推
- 当数据只有 1 组时,比较次数为 0;
- 当数据有 2 组时,比较次数为 1;
- 当数据有 3 组时,比较次数为 3;
- 当数据大于 3 组时,我们设规模为 n ,则需要的比较次数为 3+f(n-2)。
比较次数证明如下:
代码实现
#include <bits/stdc++.h>
using namespace std;
const int N = (int)1e5+5;
int arr[N], n = 10000;
struct node {
int _max, _min;
node() {
_min = ~(1<<31);
_max = 1<<31;
}
void print() {
cout << "Max = " << _max << ' ' << "Min = " << _min << endl;
}
};
void f0(int arr[], int n, node& ans) {
if (n <= 0) {
cout << "Error Input" << endl;
return ;
}
ans._max = ans._min = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > ans._max) {
ans._max = arr[i];
} else if (arr[i] < ans._min) {
ans._min = arr[i];
}
}
}
void f1(int arr[], int n, node& ans) {
if (n <= 0) {
cout << "Error Input" << endl;
} else if (n == 1) {
ans._max = ans._min = arr[0];
} else if (n == 2) {
if (arr[0] < arr[1]) {
ans._max = arr[1];
ans._min = arr[0];
} else {
ans._max = arr[0];
ans._min = arr[1];
}
} else if (n == 3) {
if (arr[0] < arr[1]) {
if (arr[0] < arr[2]) {
ans._min = arr[0];
if (arr[1] < arr[2]) {
ans._max = arr[2];
} else {
ans._max = arr[1];
}
} else {
ans._min = arr[2];
ans._max = arr[1];
}
} else {
if (arr[1] < arr[2]) {
ans._min = arr[1];
if (arr[0] < arr[2]) {
ans._max = arr[2];
} else {
ans._max = arr[0];
}
} else {
ans._min = arr[2];
ans._max = arr[1];
}
}
} else {
f1(arr, n - 2, ans);
if (arr[n - 2] < arr[n - 1]) {
if (arr[n - 1] > ans._max) {
ans._max = arr[n - 1];
}
if (arr[n - 2] < ans._min) {
ans._min = arr[n - 2];
}
} else {
if (arr[n - 2] > ans._max) {
ans._max = arr[n - 2];
}
if (arr[n - 1] < ans._min) {
ans._min = arr[n - 1];
}
}
}
}
void f2(int arr[], int n, node& ans) {
if (n <= 0) {
cout << "Error Input" << endl;
return ;
}
if (n == 1) {
ans._max = ans._min = arr[0];
return ;
}
//n/2取下界
for (int i = 0; i < n - 1; i+=2) {
if (arr[i] > arr[i + 1]) {
swap(arr[i] , arr[i + 1]);
}
}
//n/2取上界-1
ans._min = arr[0];
for (int i = 2; i < n; i+=2) {
if (arr[i] < ans._min) {
ans._min = arr[i];
}
}
//n/2取上界-1
ans._max = arr[1];
for (int i = 3; i < n; i+=2) {
if (arr[i] > ans._max) {
ans._max = arr[i];
}
}
if (n & 1) {
if(ans._max < arr[n - 1]) ans._max = arr[n - 1];
}
}
int main() {
node s0, s1, s2;
for (int i = 0; i < n; i++) arr[i] = rand();
f0(arr, n, s0);
f1(arr, n, s1);
f2(arr, n, s2);
s0.print();
s1.print();
s2.print();
return 0;
}