滑动窗口法

例1:最小连续子数组

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中知足其和 ≥ s 的长度最小的连续子数组。若是不存在符合条件的连续子数组,返回 0,如:java

输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。

可使用滑动窗口法求解:
维持一个窗口,每次计算窗口的值是否知足要求
新增一个值
在这里插入图片描述
在这里插入图片描述web

import org.omg.PortableInterceptor.INACTIVE;
import javax.sound.midi.Soundbank;
import javax.swing.*;
import java.io.IOException;
import java.util.*;


public class Main {
// private LinkedList<>
    private static Integer maxCount = 0;

    public static void main(String[] args){
        Integer[] arr = {2,3,1,2,4,3};
        System.out.println(minSubArrayLen(7,arr));
    }

    public static int minSubArrayLen(int s, Integer[] nums) {
        int start = 0;
        int end = -1;
        int minLen = nums.length + 1;   //最小长度
        int sum = 0;    //和
        while (start < nums.length){

            //每次循环生成一个新的窗口
            if (sum < s && end+1 < nums.length){
                sum = sum + nums[++end];
            }else {
                sum = sum - nums[start++];
            }

            //计算新窗口的值
            if (sum >= s){
                if ((end - start + 1) < minLen){
                    minLen = end - start + 1;
                }
            }
        }
        if (minLen == nums.length + 1){
            return 0;
        }
        return minLen;
    }
}

例2:找到字符串中全部字母异位词(leetcode 438)

给定一个字符串 s 和一个非空字符串 p,找到 s 中全部是 p 的字母异位词的子串,返回这些子串的起始索引。数组

字符串只包含小写英文字母,而且字符串 s 和 p 的长度都不超过 20100。svg

说明:spa

  • 字母异位词指字母相同,但排列不一样的字符串。
  • 不考虑答案输出的顺序。
    示例 1:

输入: s: “cbaebabacd” p: "abc"code

输出: [0, 6]xml

解释: 起始索引等于 0 的子串是 “cba”, 它是 “abc” 的字母异位词。 起始索引等于 6 的子串是 “bac”, 它是
“abc” 的字母异位词。blog

示例 2:索引

输入: s: “abab” p: "ab"token

输出: [0, 1, 2]

解释: 起始索引等于 0 的子串是 “ab”, 它是 “ab” 的字母异位词。 起始索引等于 1 的子串是 “ba”, 它是 “ab”
的字母异位词。 起始索引等于 2 的子串是 “ab”, 它是 “ab” 的字母异位词。

使用滑动窗口法

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> res = findAnagrams("cbaebabacd","abc");
        for (Integer v : res){
            System.out.println(v);
        }
    }

    public static int[] copyList(int[] list){
        int[] copyList = new int[list.length];
        for (int i=0; i<list.length; i++){
            copyList[i] = list[i];
        }
        return copyList;
    }

    public static List<Integer> findAnagrams(String s, String p) {
        int start = 0;
        int end = -1;
        int[] wordCount = new int[256];
        List<Integer> ans = new LinkedList<Integer>();
        for (int i=0; i<p.length(); i++){
            wordCount[p.charAt(i)]++;
        }
        for (int i=0; i<wordCount.length; i++){
            if (wordCount[i] == 0)
                wordCount[i] = -1;
        }
        int[] tmpCount = copyList(wordCount);


        while (start < s.length()){
            if (tmpCount[s.charAt(start)] != -1){
                if (end == -1){
                    end = start-1;
                }
                if (end+1<s.length() && tmpCount[s.charAt(end+1)]!=-1){
                    if (tmpCount[s.charAt(end+1)] > 0){
                        tmpCount[s.charAt(end+1)]--;
                        end++;
                    }else {
                        tmpCount[s.charAt(start)]++;
                        start++;
                        if (start > end){
                            end = -1;
                        }
                    }
                }else {
                    tmpCount = copyList(wordCount);
                    start = end + 2;
                    end = -1;
                }
            }else {
                start++;
            }
            if (end - start + 1 == p.length()){
                ans.add(start);
            }
        }

        return ans;
    }

}