滑動窗口問題歸納

今後遇到滑動窗口問題都可先按該模板來寫

1. leetcode:3. Longest Substring Without Repeating Characters

Given a string, find the length of the longest substring without repeating characters.

Example 1:

Input: "abcabcbb"
Output: 3 
Explanation: The answer is "abc", with the length of 3. 

代碼如下:

這是一個滑動窗口+查找表:也就是滑動窗口中的數據用數組、set、map等等數據結構來保存

class Solution {
   public int lengthOfLongestSubstring(String s) {
       int[]  freq = new int[256];//在l 到 r之間維護一個數組來表示滑動窗口, 
                                    //也可以定義一個hasnmap來維持一個窗口
       int l = 0, r = -1;
       int res = 0;
       while(l< s.length()){
           if(r+1 < s.length() && freq[s.charAt(r+1)] == 0){//滑動窗口中沒出現過該字母
               freq[s.charAt(++r)] ++;
           }else{//滑動窗口中出現過該字母,則進行窗口移動
               freq[s.charAt(l++)] --;
           }
           res = Math.max(res, r-l+1);
       } 
      return res;
    }
}

2.220. Contains Duplicate III     Given an array of integers, find out whether there are two distinct indices i and j in the array such that the absolute difference between nums[i] and nums[j] is at most t and the absolute difference between i and j is at most k.

Example 1:

Input: nums = [1,2,3,1], k = 3, t = 0
Output: true

這是一個滑動窗口+查找表(滑動窗口長度是可變的):

代碼如下:

public class Solution {
    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        if (nums == null || nums.length == 0 || k <= 0) {
            return false;
        }

        TreeSet<Integer> values = new TreeSet<>();
        for (int ind = 0; ind < nums.length; ind++) {

            Integer floor = values.floor(nums[ind] + t);
            Integer ceil = values.ceiling(nums[ind] - t);
            if ((floor != null && floor >= nums[ind])
                    || (ceil != null && ceil <= nums[ind])) {
                return true;
            }

            values.add(nums[ind]);
            if (ind >= k) {
                values.remove(nums[ind - k]);
            }
        }

        return false;
    }
}

 

3.219. Contains Duplicate II

Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k.

Example 1:

Input: nums = [1,2,3,1], k = 3
Output: true

這是一個滑動窗口+查找表(滑動窗口長度是不可變的):

代碼如下:

class Solution {
   public boolean containsNearbyDuplicate(int[] nums, int k) {
        Set<Integer> set = new TreeSet<Integer>();
        for(int i=0;i<nums.length; i++){
             if(i>k){
                set.remove(nums[i-k-1]);
            }
            if(!set.add(nums[i])){
                return true;
            }
        }
     return false;   
 }
}

 

3.209. Minimum Size Subarray Sum

Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead.

Example: 

Input: s = 7, nums = [2,3,1,2,4,3]
Output: 2
Explanation: the subarray [4,3] has the minimal length under the problem constraint.

這是一個完全用滑動窗口來解決的問題(同時滑動窗口長度是可變的

代碼如下:

class Solution {
    public int minSubArrayLen(int s, int[] a) {
        int l =0, r=-1,res =a.length+1 , sum =0;
        while(l<a.length){
            if(r+1 < a.length && sum<s){
                sum += a[++r];
            }else{
                sum -= a[l++];
            }
            
            if( sum>= s){
               res = Math.min(res, r-l+1);
            }
        }
        return res == a.length+1 ? 0:res;
   }
}

//或者
class Solution {
    public int minSubArrayLen(int s, int[] a) {
       if (a == null || a.length == 0)
       return 0;
  
       int left = 0, right = 0, sum = 0, min = Integer.MAX_VALUE;
       while (right < a.length) {
           sum += a[right++];
           while (sum >= s) {  //是while而不是if
              min = Math.min(min, right - left);
              sum -= a[left++];
       }
    }
      return min == Integer.MAX_VALUE ? 0 : min;
   }
}

可以分爲兩類:1.滑動窗口

                          2.滑動窗口+查找表(也就是滑動窗口用什麼數據結構來存儲一般有數組、set、map),同時滑動窗口長度可以                                分爲可變與不可變

根據規律滑動窗口問題可寫一個模板如下:(適用於滑動窗口  或者 滑動窗口+查找表同時滑動窗口長度可變)

class Solution {
    public int minSubArrayLen(int s, int[] a) {
        int l =0, r=-1 .....;//定義滑動窗口兩下標
        while( l<輸入長度 ){
            if(r+1 < a.length && 另一個條件){// r+1要小於輸入長度
               
// 只做l++ 或者 ++r相關操作
            }else{
//只做l++ 或者 ++r相關操作

                
            }
 
//  做除了l++ 或者 r++之外的其他操作         
        }
       
   }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章