leetcodeタイトルブラシ(43) - 239スライディングウィンドウ最大

アレイ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

ヒント:
あなたは、常に効果的なそのKをとることができる、入力配列の場合には、1つの≤K≤入力配列のサイズを空にされていません。

考える:
反復数を両端キューに格納し、Lで処理され、Rは、ウィンドウの左と右の境界線をマーク。本当にキュー番号に保存されているが、配列インデックスの位置、および配列の数に対応する値が降順にソートすることがありません。現在の反復回数は、チームの尾の値よりも大きい場合には、大小の両方の要件を満たすために再びキューまで尾の値をポップする必要があります。トラバーサル、LとRの両方が0で始まるウィンドウを形成するプロセスは、このプロセスは、最大値でない場合、Lは、右側にRを移動しません。右、すべての移動とともにウィンドウサイズ、LとRを形成する場合、最初のチームはない最初の値が必要なポップ力、現在のウィンドウである場合、決定配列インデックス値は、[L、R]であります最初はチームの最大数です。

例:

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

解释过程中队列中都是具体的值,方便理解,具体见代码。
初始状态:L=R=0,队列:{}
i=0,nums[0]=1。队列为空,直接加入。队列:{1}
i=1,nums[1]=3。队尾值为1,3>1,弹出队尾值,加入3。队列:{3}
i=2,nums[2]=-1。队尾值为3,-1<3,直接加入。队列:{3,-1}。此时窗口已经形成,L=0,R=2,result=[3]
i=3,nums[3]=-3。队尾值为-1,-3<-1,直接加入。队列:{3,-1,-3}。队首3对应的下标为1,L=1,R=3,有效。result=[3,3]
i=4,nums[4]=5。队尾值为-3,5>-3,依次弹出后加入。队列:{5}。此时L=2,R=4,有效。result=[3,3,5]
i=5,nums[5]=3。队尾值为5,3<5,直接加入。队列:{5,3}。此时L=3,R=5,有效。result=[3,3,5,5]
i=6,nums[6]=6。队尾值为3,6>3,依次弹出后加入。队列:{6}。此时L=4,R=6,有效。result=[3,3,5,5,6]
i=7,nums[7]=7。队尾值为6,7>6,弹出队尾值后加入。队列:{7}。此时L=5,R=7,有效。result=[3,3,5,5,6,7]

一例として、そのR = I、L = R-見出さ K + 1。キューの値は、ウィンドウを変更するたびに、あなたは唯一のチームの最初のウィンドウの値がライン上にまだあるかどうかを判断する必要があるので、降順でソートされているので。
最初のチームの値がウィンドウ内かどうかを判断するためにのでキューは、目標値のストレージアレイの代わりに、直接の値の下に格納される理由を説明、配列のインデックス値は、非常に便利ですが、配列のインデックスの値を取ることによって、非常に便利ではありません。

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums == null || nums.length < 2) return nums;
        // 双向队列 保存当前窗口最大值的数组位置 保证队列中数组位置的数值按从大到小排序
        LinkedList<Integer> queue = new LinkedList();
        // 结果数组
        int[] result = new int[nums.length-k+1];
        // 遍历nums数组
        for(int i = 0;i < nums.length;i++){
            // 保证从大到小 如果前面数小则需要依次弹出,直至满足要求
            while(!queue.isEmpty() && nums[queue.peekLast()] <= nums[i]){
                queue.pollLast();
            }
            // 添加当前值对应的数组下标
            queue.addLast(i);
            // 判断当前队列中队首的值是否有效,就是是否在左边界范围内
            if(queue.peek() < i-k+1){
                queue.poll();   
            } 
            // 当窗口长度为k时 保存当前窗口中最大值
            if(i+1 >= k){
                result[i+1-k] = nums[queue.peek()];
            }
        }
        return result;
    }
}
彼は199元の記事を発表 ウォンの賞賛684 ビュー890 000 +

おすすめ

転載: blog.csdn.net/u012124438/article/details/104085052