• 双指针之滑动窗口(长度最小的子数组 和 和为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; } }

     

  • 相关阅读:
    燕园笔记之一——穿梭
    openvc学习笔记(1)——简单应用
    匆匆过客
    opencv学习(3)——高斯平滑图像
    为什么(win10系统)电脑上面的鼠标(触摸板)突然用不了?怎么开启和关闭、
    SqlServer自动备份数据库
    CodeSmith批量生成实体类
    XML文件的序列化和反序列化
    AjaxPro的使用
    设计模式之——策略模式
  • 原文地址:https://www.cnblogs.com/shan333/p/15406292.html
Copyright © 2020-2023  润新知