求数组中比左边元素都大同时比右边元素都小的元素

484 阅读1分钟

求数组中比左边元素都大同时比右边元素都小的元素

求数组中比左边元素都大同时比右边元素都小的元素,返回这些元素的索引

要求时间复杂度 O(N)。比如:

输入:[2, 3, 1, 8, 9, 20, 12]

输出:3, 4

解释:数组中 8, 9 满足题目要求,他们的索引分别是 3、4

解析: 对于数组中每个元素,如果它比左侧最大值要大,比右侧最小值要小,就满足条件; 所以可以定义两个数组maxLeft、minRight,分别存储第i个元素左侧的最大值和右侧最小值,则可以通过 maxLeft[i] < arr[i] && minRight[i] > arr[i]来判断。 时间复杂度为O(N)

代码:

void test(int a[],int length){

    // 左边最大值
    int maxLeft[length];
    maxLeft[0] = a[0];
    
    for (int i = 1; i < length - 1; i ++) {
        maxLeft[i] = MAX(a[i - 1], maxLeft[i - 1]);
    }

    // 右边最小值,数组
    
    int minRight[length];
    minRight[length - 1] = a[length - 1];
    
    for (int i = length - 1 - 1; i > 0; i --) {
        minRight[i] = MIN(minRight[i + 1], a[i + 1]);
    }

    // 循环
    
    for (int i = 0; i < length; i ++) {
        if (a[i] > maxLeft[i] && a[i] < minRight[i]) {
            printf("%d\n", i);
        }
    }
}

优化:

以上分析中的左边最大值,可以不必开辟数组,可以定义一个变量随循环进行计算,优化后代码如下:

void test1(int a[],int length){

    // 左边最大值
    int maxLeft = a[0];

    // 右边最小值,数组
    
    int minRight[length];
    minRight[length - 1] = a[length - 1];
    
    for (int i = length - 1 - 1; i > 0; i --) {
        minRight[i] = MIN(minRight[i + 1], a[i + 1]);
    }

    // 循环

    for (int i = 0; i < length; i ++) {
        if (i > 0) {
            // 更新左边最大值
            maxLeft = MAX(maxLeft, a[i - 1]);
        }
        if (a[i] > maxLeft && a[i] < minRight[i]) {
            printf("%d\n", i);
        }
    }
}