leetCode-239 滑动窗口最大值

488 阅读2分钟

描述

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

示例:

输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7] 
解释: 

  滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

思路1

  1. 求出前k个数中的最大元素max
  2. 移动数组,从k+1开始遍历,如果nums[k+1] > max此时`max = nums[k+1]
[3  -1  -3] 5
5 > 3
max = 5
  1. 如果nums[k+1] <= max,需要判断当前的max是否位于窗口的开始位置,
  2. 如果max是否位于窗口的开始位置,则剔除max,重新在当前的窗口中确定最大值
[3, 2, 1] 2
3 > 2 但是 3位于窗口开始,需要剔除,重新确定最大值为2
  1. 如果max不在窗口的开始位置,说明当前的max还是新的窗口中的最大值,继续遍历。

代码

// 求出start-end之间的最大值
int maxValue(int *array, int start, int end) {
    int max = array[start];
    for(int i = start+1; i <= end; i++) {
        max = array[i] > max ? array[i] : max;
    }
    return max;
}

int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize) {
    *returnSize = numsSize-k+1;
    int *res = (int*)malloc(sizeof(int)*(*returnSize));
    // 先求出初始窗口的最大值max
    int max = maxValue(nums, 0, k-1);
    for(int i = 0; i < *returnSize-1; i++) {
    	// 赋值
        res[i] = max;
        // 和当前窗口的下一个值进行对比,求出新窗口的max值
        if(max > nums[i+k]) {
            if(max == nums[i]) {
                max = maxValue(nums, i+1, i+k);
            }
        }else {
            max = nums[i+k];
        }
    }
    // 循环的结束只求出最后一个窗口的最大值,需要再执行一次赋值操作
    res[*returnSize-1] = max;
    return res;
}

思路2

维持一个递减的数组,数组中保存着当前窗口中递减的元素,每次拿最大的元素和当前窗口下一个元素对比,判断过程和思路1类似,只不过是求窗口最大值的方式不一样。

int* maxSlidingWindow1(int* nums, int numsSize, int k, int* returnSize){
    int *queue = (int*)malloc(sizeof(int)*numsSize);
    *returnSize = numsSize - k + 1;
    int *res = (int*)malloc(sizeof(int)*(*returnSize));
    int resIndex = 1;
    int front = 0;
    int rear = -1;
    for(int i = 0; i < numsSize; i++) {
        // 正常插入
        while(rear >= front && nums[i] > queue[rear]) {
            rear--;
        }
        queue[++rear] = nums[i];
        if(i < k) {
        	// i<k的时候只是构建递减数组,只能得到res[0]的值
            res[0] = queue[front];
        }else {
            // 如果需要删除的元素为当前窗口最大值,递减数组起始索引+1
            if(queue[front] == nums[i-k]) {
                front++;
            }
            // 新窗口的最大值为新数组的第一个元素
            res[resIndex++] = queue[front];
        }
    }
    return res;
}