题目


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;
}