滑动窗口的最大值 LintCode

这个是我完成的第一个 LintCode 上面的超难的题目,特此纪念一下,并分享一下结题的思路。

原题目链接:滑动窗口的最大值 

问题描述:

给出一个可能包含重复的整数数组,和一个大小为 k 的滑动窗口, 从左到右在数组中滑动这个窗口,找到数组中每个窗口内的最大值。

样例说明:

        给出数组 [1,2,7,7,8], 滑动窗口大小为 k = 3. 返回 [7,7,8].
	解释:
	最开始,窗口的状态如下:
	[|1, 2 ,7| ,7 , 8], 最大值为 7;
	然后窗口向右移动一位:
	[1, |2, 7, 7|, 8], 最大值为 7;
	最后窗口再向右移动一位:
	[1, 2, |7, 7, 8|], 最大值为 8.

问题分析:

1.一开始的时候,我们将窗口置于最左边,遍历窗口中的值,得到最大值。
2.将窗口向右移动,在这个移动的过程中,我们会将上一个窗口的最左边一个元素移除,将紧邻窗口的右边的元素移入,
    这时, 情况1: 如果我们移入的这个值是不小于上一个窗口的最大值,那么此时当前窗口的最大值就是新移入的这个值
情况2: 如果移入的这个值要小于上一个窗口的最大值,并且移除的这个元素正好就是上一个窗口的最大值,那么我们就要重新从当前窗口中选出最大值

情况3: 如果移入的这个值小于上一个窗口的最大值,并且移除的这个元素也不是上一个最大值,那么当前窗口的最大值也是上一个窗口的最大值

实现代码:

/**
 * @author 作者 John L:
 * @version 创建时间:May 11, 2018 8:46:36 PM
 */
public class TestMaxSlidingWindow {
    public ArrayList<Integer> maxSlidingWindow(int[] nums, int k) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        if(nums == null || nums.length == 0) return result;
        //第一个窗口,先遍历窗口值选出最大值
        int greatestNumInLastWindow = findGreatestNumBetween(nums, 0, k - 1);
        result.add(greatestNumInLastWindow);
        
        for(int i = 1; i < nums.length - k + 1; i ++){
            //将窗口右移,start是窗口的最左边元素座标,end是窗口最右边元素座标
            int start = i;
            int end = start + k - 1;
            if (nums[end] >= greatestNumInLastWindow) {
            	//对应情况1,将新移入的元素作为窗口最大值
		greatestNumInLastWindow = nums[end];
	    } else if(nums[start - 1] == greatestNumInLastWindow){
		//对应情况2, 重新从窗口中选出最大值
		greatestNumInLastWindow = findGreatestNumBetween(nums, start, end);
	    }
            	//情况3则什么都不用做,直接使用上一个窗口的最大值
            //将当前窗口的最大值加入result中
            result.add(greatestNumInLastWindow);
        }
        return result;
     }
     
    /**
     * 窗口位置从start到end, 遍历窗口中的值, 选出最大值
     */
	private int findGreatestNumBetween(int[] nums, int start, int end) {
		int temp = Integer.MIN_VALUE;
		for (int i = start; i <= end; i++) {
			temp = temp < nums[i] ? nums[i] : temp;
		}
		return temp;
	}
}

点赞