source:http://soj.sysu.edu.cn/show_problem.php?pid=1005&cid=2390
题意
给出一个序列,找出满足下列条件的数的数目:
1.这个数它比左边的数都大
2.这个数比它右边的数都小
算法
最简单的方法
就是写两个函数,返回index左边最大的数和index右边最小的数,然后和arr[index]比较。满足上述条件则计数+1.
bool findMax(int index)
{
for(int i = 0; i < index; i++)
{
if(arr[i] > arr[index])
return false;
}
return true;
}
bool findMin(int index)
{
for(int i = index + 1; i < v.size(); i++)
{
if(arr[i] < arr[index])
return false;
}
return true;
}
这是最直观的方法,但是复杂度高,达到o( n2 ),让人不满意。
优秀的改进方法
用两个数组分别记录index左边最大的数和index右边最小的数。
分别用两个循环就可以,找出每一个index左边最大的数,和每一个index右边最小的数。
然后再用一次循环来计数,就可以得到结果。
复杂度为o(n);
注意
这里因为题目没有说序列中的数的范围,所以逻辑的最小值要足够小和逻辑最大值要足够大。
优秀改进方法源代码
#include <iostream>
#include <algorithm>
using namespace std;
// 输入的数字序列
int arr[105];
// 记录index右边的最小值
int rightLeast[105];
// 记录index左边的最大值
int leftBiggest[105];
void findRightLeast(int len) {
// 逻辑最大值
rightLeast[len-1] = 999999;
for(int i = len - 2; i > -1; i--) {
rightLeast[i] = min(arr[i+1], rightLeast[i+1]);
}
}
void findLeftBiggest(int len) {
// 逻辑最小值
leftBiggest[0] = -999999;
for(int i = 1; i < len; i++) {
leftBiggest[i] = max(arr[i-1], leftBiggest[i-1]);
}
}
int main() {
int len;
while(cin >> len) {
// 读入
for(int i = 0; i < len; i++) {
cin >> arr[i];
}
// 寻找index左边最大值和index右边最小值
findLeftBiggest(len);
findRightLeast(len);
// 计数
int num = 0;
for(int i = 0; i < len; i++) {
if(arr[i] > leftBiggest[i] && arr[i] < rightLeast[i]) {
num++;
}
}
cout << num << endl;
}
return 0;
}