LeetCode Hot100 - 子串篇

前言

        挑战一个月刷完力扣的hot100,记录一下每题的思路~

        这次是子串相关的题目

(1)560. 和为 K 的子数组

        ①暴力枚举,使用一个变量sum记录以l开头r结尾的情况

class Solution {
    public int subarraySum(int[] nums, int k) {
        int res=0;
        // 枚举每种情况
        for(int l=0;l

        ②前缀和+map,map记录每种前缀和出现的次数。若位置i的前缀和为pre,map中存在pre-k的前缀和,即存在某位置到i的和为k,统计次数即可

class Solution {
    Map map = new HashMap<>(); // 每种前缀和出现次数
    public int subarraySum(int[] nums, int k) {
        int res=0, pre=0;
        map.put(0,1);
        for(int i=0;i

(2)239. 滑动窗口最大值

        ①优先队列,记录值和下标,按降序(越大越优先),每次移除下标越界元素,取最大值

class Solution {
    // 优先队列,存值和下标,按值降序,即越大优先级越高
    PriorityQueue pq = new PriorityQueue<>((a,b)->Integer.compare(b[0],a[0]));
    List res = new ArrayList<>();
    public int[] maxSlidingWindow(int[] nums, int k) {
        for(int i=0;i

        ②单调递减双端队列。若l不可能选到l。每次入队为靠后元素,若该元素大于队尾元素,队尾不可能再选到,直接出队。队列保留目前最大值和其后递减较小值。最大值移出滑动窗口时,将其出队

class Solution {
    List res = new ArrayList<>();
    Deque queue = new ArrayDeque<>(); // 单调递减双端队列
    public int[] maxSlidingWindow(int[] nums, int k) {
        for(int i=0;i=k&&queue.peekFirst()==nums[i-k])queue.pollFirst();
            // 加入当前元素,满足单调递减
            while(!queue.isEmpty()&&queue.peekLast()=k-1)res.add(queue.peekFirst());
        }
        return res.stream().mapToInt(Integer::intValue).toArray();
    }
}

        ③思路同上一种,单调队列记录下标,用于队头下标越界判断,更好理解

class Solution {
    List res = new ArrayList<>();
    Deque deque = new ArrayDeque<>(); // 单调递减双端队列
    public int[] maxSlidingWindow(int[] nums, int k) {
        for(int i=0;i=k&&deque.peekFirst()<=i-k)deque.pollFirst();
            // 遍历到k-1时开始取队头,即目前最大值
            if(i>=k-1)res.add(nums[deque.peekFirst()]);
        }
        return res.stream().mapToInt(Integer::intValue).toArray();
    }
}

        ④分组+最大前后缀。k个数一组,计算每组最大前后缀。窗口起始值i,若为k的整数倍,即窗口恰好为一组;否则,窗口跨越两个分组,取前一个分组最大后缀和后一个分组最大前缀的最大值

class Solution {
    List res = new ArrayList<>();
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n = nums.length;
        int[] prefixMax=new int[n], suffixMax=new int[n];
        for(int i=0,j=n-1;i

(3)76. 最小覆盖子串

        滑动窗口。map和count分别记录t和滑动窗口的字符数,check判断count不小于map,即滑动窗口满足条件。r扩张直到check为true,然后收缩l直到不满足,记录最短滑动窗口

class Solution {
    Map map = new HashMap<>();
    Map count = new HashMap<>();
    public String minWindow(String s, String t) {
        if(s.length()

总结

        ①子串双指针暴力枚举;map记录每种前缀和出现次数,统计pre-k存在次数

        ②和为K的子串优先队列记录值和下标,值大优先,下标限界;单调递减双端队列,位于前面且更小的值不会再被选中;分组+最大前后缀,预处理分组的前后缀,滑动窗口恰为分组,或跨越两个分组

        ③滑动窗口最大值滑动窗口,r扩张找到满足的情况,l收缩尽可能最短

你可能感兴趣的:(力扣hot100,leetcode,算法,子串)