2

题目大意:

本题输入一个序列,包含N个正整数,如果一个数左边的所有数都比它小、右边的所有数都比它大,那么称这个数为序列的一个pivot。求序列中pivot的个数。

算法思路:

由于判断任意位置的数字是否是pivot必须得知道它是否比左边的都大,比右边的都小,那么就使用数组leftMaxrightMin分别保存当前位置的左边最小的数和右边最大的数,先从左往右遍历,如果当前位置j==0,那么就设置其左边最小的数字为-1,如果不是第一个数字就在j-1和j-1左边的所有最小的数字中选择一个更小的数字作为当前位置的左边的最小数字,然后从右往左遍历,如果当前的位置k==N-1,那么就设置其右边的最大的数字为0x3ffffff,如果不是最后一个数字,就在k+1和k+1右边的所有数字中选择一个更大的数字作为当前数字右边所有数字中的最大数。最后再遍历一次数组元素,将符合条件的元素添加进set集合中,然后输出即可。

注意点:

1、必须得输出两行,也就就是在没有pivot的时候需要输出0然后第二行得输出空行,测试点2考察。

提交结果:

截屏2020-10-22 上午10.08.22.png

AC代码:

#include <set>
#include <cstdio>

using namespace std;

int main(){
    int N;
    scanf("%d",&N);
    int a[N];
    for (int i = 0; i < N; ++i) {
        scanf("%d",&a[i]);
    }
    int leftMax[N];// 保存当前位置的左边最大的数字
    int rightMin[N];// 保存当前位置的右边最小的数字
    for (int j = 0; j < N; ++j) {
        if(j==0){
            leftMax[j] = -1;//最左边的数字左边没有数字
        } else  {
            leftMax[j] = a[j-1]>leftMax[j-1]?a[j-1]:leftMax[j-1];
        }
    }
    for (int k = N-1; k >=0 ; --k) {
        if(k==N-1){
            rightMin[k] = 0x3fffffff;
        } else {
            rightMin[k] = a[k+1]<rightMin[k+1]?a[k+1]:rightMin[k+1];
        }
    }
    set<int> pivots;//pivot集合
    for (int l = 0; l < N; ++l) {
        if(a[l]>leftMax[l]&&a[l]<rightMin[l]){
            pivots.insert(a[l]);
        }
    }
    printf("%d\n",pivots.size());
    set<int>::iterator it;
    for(it=pivots.begin();it!=pivots.end();++it){
        if(it!=pivots.begin()) printf(" ");
        printf("%d",*it);
    }
    printf("\n");
    return 0;
}

乔梓鑫
569 声望17 粉丝

主要分享个人学习经验和心得