双指针之滑动窗口(长度最小的子数组 和 和为s的连续正数序列)

 

 

双指针之滑动窗口 (长度最小的子数组;和为s的连续正数序列)

 

1, 什么时候使用?

(与子数组/字符串 有关的题目)~如果给了某个具体值的target,即用滑动窗口

不然就双指针(一般做法,左边< 右边,依据条件左边和右边都不断靠近)

 滑动窗口:是双指针的题目
找出一个数组中满足一定条件的子数组问题,字符串也可以看成数组。看到子数组问题,就是DP回溯滑动窗口这三种之一

 2,滑动窗口的通用框架 1:(例题:209_长度最小的子数组)

题特点一:题目给定了具体的值target,这个target条件的可能弹性空间比较大了

  【例如题目 要求某种情况下>= target】,而大于target的可能情况就会比较多了


 * ① 先移动右指针确定窗口的大致可能范围(在这大致可能范围里找到最优范围),然后暂时固定住右指针,
 * ② 在满足条件(满足target下):不断的移动左指针,缩小窗口
 * ③ 当不满足target了,又开始移动右指针,然后。。。。。又确定下来窗口的大致可能范围

     (在这大致可能范围里找到最优范围),然后暂时固定住右指针。。。
 * 特点2,形式上的特点(左右指针移动的方向):是一开始左右指针,同方法移动)

public class 滑动窗口的通用框架 1{
     public String slidingWindow(String s, String t) {
            // 起始的时候,都位于 0,同方向移动
            int left = 0;
            int right = 0;
            int sLen = s.length();
            while (right < sLen) {
                char c = s.charAt(right);
                right++;
                //对状态做修改
                while ( 满足某种条件 ) {
                   //更新ans可能的地方之一
                    char c1 = s.charAt(left);
                    left++;
                    //对状态做修改
                }
                //更新ans可能的地方之二
            }
            return 需要的结果变量;
        }
}

 例题:

package 数组;
/**
 * https://leetcode-cn.com/problems/minimum-size-subarray-sum/
 * @author Huangyujun
 * 
 * 注意细节:当找到满足条件的窗口时,需要固定右边界,
 * 逐渐移动左边界(缩小窗口大小),直到窗口元素和不满足要求,再改变右边界。使用while循环缩小!
 *
 */
public class _209_长度最小的子数组 {
    public int minSubArrayLen(int s, int[] nums) {
        int n = nums.length;
        if (nums == null || n == 0) return 0;
        int ans = Integer.MAX_VALUE;
        int left = 0, right = 0;
        int sum = 0;
        while (right < n) {
            sum += nums[right++];
            while (sum >= s) {
                ans = Math.min(ans, right - left);
                sum -= nums[left++];
            }
        }
        return ans == Integer.MAX_VALUE ? 0 : ans;
    }
}

 

3,滑动窗口的通用框架 2:(例题:57_和为s的连续正数序列)
做题特点 一:题目给定了具体的值target,这个target条件的可能弹性空间唯一了

【例如题目 要求某种情况下= target】,而等于target的可能情况在“暂时固定下的范围窗口中情况就是固定下该窗口呀”

* ① == target,这种直接通过判断找窗口范围,找到一个固定窗口范围后,移动左边指针(达到整体窗口向前移动)

  去找下一个固定窗口范围
* 这类题:直接分:①== target,② < target ,③ > target 来找合适的固定窗口范围

public class 滑动窗口的通用框架 2{
    public String slidingWindow(int target) {
           // 起始的时候,同方向移动
           int left = 1;
           int right = 2;
           while (l < r) {
                更新ans
                if( ans == target){
                    //需要的结果,得到了一个
                    l++;
                }else if(ans < target){    //比target小,右指针往前移动,扩大范围
                    r++;
                }else{        //比target大,左指针往前移动,缩小范围
                    l++;
                }
              
           }
           return 需要的结果变量;
       }
}

例题:

package 数组;

/**
 * https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/
 */
import java.util.ArrayList;
import java.util.List;

public class _57_和为s的连续正数序列 {
    /**
     * 细节:正数 思路: 1、双指针技术,就是相当于有一个窗口,窗口的左右两边就是两个指针 2、根据窗口内值之和来确定窗口的位置和宽度。
     */
    public int[][] findContinuousSequence(int target) {
        List<int[]> vec = new ArrayList<int[]>();
        int l = 1, r = 2;
        while(l < r) {
            //求和公式
            int sum = (l + r) * (r - l + 1) / 2;
            if (sum == target) {
                int[] res = new int[r - l + 1];
                for (int i = l; i <= r; ++i) {
                    res[i - l] = i;
                }
                vec.add(res);
                l++;    //找到之后,左边指针往前挪动,意味着整个窗口往前挪动
            } else if (sum < target) {
                r++;
            } else {
                l++;
            }
        }
        return vec.toArray(new int[vec.size()][]);
    }

}

 

✿ 没给某个具体值的target,使用一般双指针思路(一般做法,左边< 右边,依据条件左边和右边都不断靠近):

例题:(盛最多水的容器)

// https://leetcode-cn.com/problems/container-with-most-water/
//正解:双指针法 public class Solution { public int maxArea(int[] height) { int l = 0, r = height.length - 1; int ans = 0; while (l < r) { //面积公式 高:最小的 【左柱子,右柱子】 int area = Math.min(height[l], height[r]) * (r - l); ans = Math.max(ans, area); // 需要找小的:(目的:去获取那个小柱子中的最大值) if (height[l] <= height[r]) { ++l; } else { --r; } } return ans; } }

 

 

 

 

 

 

posted @ 2021-10-14 13:24  一乐乐  阅读(137)  评论(0编辑  收藏  举报