题目

18分的超时解法
点击查看代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
int n; scanf("%d",&n);
vector<int> v(n);
for(int i =0;i<n;i++){
scanf("%d",&v[i]);
}
int a=0,c=n-1;
vector<int> ans;
for(int b =0;b<n;b++){
// 查询[a,b] 是不是都比b小
while(v[a] <= v[b] && a != b){
a++;
}
// 查询[b,c] 是不是都比b大
while(v[c] >= v[b] && c != b){
c--;
}
if(a==b && b==c) ans.push_back(v[b]);
a=0; c=n-1;
}
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++){
if(i>0) {
printf(" %d",ans[i]);
}
else {
printf("%d",ans[i]);
}
}
cout<<endl;
return 0;
}
正确解法
从左到右遍历数组,记录每个位置左侧的最大值 leftMax。
从右到左遍历数组,记录每个位置右侧的最小值 rightMin。
如果一个元素 v[i] 大于等于其左侧的最大值 leftMax[i],并且小于等于其右侧的最小值 rightMin[i],那么它就是一个合法的 pivot。
点击查看代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n;
scanf("%d", &n);
vector<int> v(n);
for (int i = 0; i < n; i++) {
scanf("%d", &v[i]);
}
// 预处理 leftMax 数组:leftMax[i] 表示 v[0..i-1] 的最大值
vector<int> leftMax(n);
leftMax[0] = v[0];
for (int i = 1; i < n; i++) {
leftMax[i] = max(leftMax[i - 1], v[i - 1]);
}
// 预处理 rightMin 数组:rightMin[i] 表示 v[i+1..n-1] 的最小值
vector<int> rightMin(n);
rightMin[n - 1] = v[n - 1];
for (int i = n - 2; i >= 0; i--) {
rightMin[i] = min(rightMin[i + 1], v[i + 1]);
}
vector<int> ans;
for (int i = 0; i < n; i++) {
// 判断 v[i] 是否 >= 左侧所有元素的最大值,且 <= 右侧所有元素的最小值
if ((i == 0 || v[i] >= leftMax[i]) && (i == n - 1 || v[i] <= rightMin[i])) {
ans.push_back(v[i]);
}
}
printf("%d\n", (int)ans.size());
for (int i = 0; i < ans.size(); i++) {
if (i > 0) {
printf(" %d", ans[i]);
} else {
printf("%d", ans[i]);
}
}
printf("\n");
return 0;
}
浙公网安备 33010602011771号