LeetCode热题100——滑动窗口/子串

news/2025/2/22 1:53:44

文章目录

  • 1. 无重复字符的最长子串
    • 1.1 题目链接
    • 1.2 题目描述
    • 1.3 解题代码
    • 1.4 解题思路
  • 2. 找到字符串中所有字母异位词
    • 2.1 题目链接
    • 2.2 题目描述
    • 2.3 解题代码
    • 2.4 解题思路
  • 3、和为 K 的子数组
    • 3.1 题目链接
    • 3.2 题目描述
    • 3.3 解题代码
    • 3.4 解题思路
  • 4. 滑动窗口最大值
    • 4.1 题目链接
    • 4.2 题目描述
    • 4.3 解题代码
    • 4.4 解题思路
  • 5. 最小覆盖子串
    • 5.1 题目链接
    • 5.2 题目描述
    • 5.3 解题代码
    • 5.4 解题思路


1. 无重复字符的最长子串

1.1 题目链接

点击跳转到题目位置

1.2 题目描述

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串的长度。

提示:

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成

1.3 解题代码

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int left = 0;
        int right = -1;
        int n = s.length();
        int len = 0;
        Set<Character> hash = new HashSet<Character>();
        while(right < n - 1){
            ++right;
            char ch = s.charAt(right);
            if(!hash.contains(ch)){
                hash.add(ch);
            } else{
                while(hash.contains(ch)){
                    hash.remove(s.charAt(left));
                    ++left;
                }
                hash.add(ch);
            }
            len = Math.max(len, right - left + 1);
        }
    return len;
    }
}

1.4 解题思路

  1. 滑动窗口解决该问题。
  2. 右指针右移,如果当前所指的字符不在集合里面,直接把该字符添加进字符中;如果当前所指的字符在集合里面,去除左指针所指的字符,并右移动,直到右指针所指的字符在集合中查询不到,最后再将右指针所指的字符添加进去。
  3. 再上述操作执行完毕后更新一下最长的长度。

2. 找到字符串中所有字母异位词

2.1 题目链接

点击跳转到题目位置

2.2 题目描述

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
提示:

  • 1 <= s.length, p.length <= 3 * 104
  • s 和 p 仅包含小写字母

2.3 解题代码

class Solution {
    boolean judge(int[] hash1, int[] hash2){
        for(int i = 0; i < 26; ++i){
            if(hash1[i] != hash2[i]){
                return false;
            }
        }
        return true;
    }

    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> res = new ArrayList<>();
        if(s.length() < p.length()){
            return res;
        }
        int[] hash1 = new int[26];
        int[] hash2 = new int[26];
        for(int i = 0; i < p.length(); ++i){
            hash1[s.charAt(i) - 'a']++;
            hash2[p.charAt(i) - 'a']++;
        }
        if(judge(hash1, hash2) == true){
            res.add(0);
        }
        int left = 0;
        int right = p.length() - 1;
        while(right < s.length() - 1){
            right++;
            hash1[s.charAt(left) - 'a']--;
            hash1[s.charAt(right) - 'a']++;
            left++;
            if(judge(hash1, hash2) == true){
                res.add(left);
            }
        }
        return res;
    }
}

2.4 解题思路

  1. 定长滑动窗口问题。
  2. 用哈希表来统计滑动窗口中各字符的数量,统计p字符的数量,如果字符数量相等,则将字符串中第一个字符的下标放入结果数组中。

3、和为 K 的子数组

3.1 题目链接

点击跳转到题目位置

3.2 题目描述

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。
子数组是数组中元素的连续非空序列。

提示:

  • 1 <= nums.length <= 2 * 104
  • -1000 <= nums[i] <= 1000
  • -107 <= k <= 107

3.3 解题代码

class Solution {
    public int subarraySum(int[] nums, int k) {
        HashMap<Integer, Integer> hash = new HashMap<>();
        int num = 0;
        int ret = 0;
        hash.put(0, 1);
        for(int i = 0; i < nums.length; ++i){
            num += nums[i];
            if(hash.containsKey(num - k)){
                ret += hash.get(num - k);
            }
            hash.put(num, hash.getOrDefault(num, 0) + 1);
        }   
        return ret;
    }
}

3.4 解题思路

  1. 哈希表+前缀和。
  2. 首先先将哈希表中0的个数设置为1。
  3. 每次统计当前前缀和,将哈希表中的值+1。
  4. 累计统计结果,每次加上当前哈希表中 前缀和 - k 的数量。

4. 滑动窗口最大值

4.1 题目链接

点击跳转到题目位置

4.2 题目描述

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 。

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104
  • 1 <= k <= nums.length

4.3 解题代码

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        Deque<Integer> deque = new LinkedList<Integer>();
        int n = nums.length;
        int[] ret = new int[n - k + 1];
        for(int i = 0; i < k; ++i){
            while(!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]){
                deque.pollLast();
            }
            deque.offerLast(i);
        }
        ret[0] = nums[deque.peekFirst()];
        for(int i = k; i < n; ++i){
            while(!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]){
                deque.pollLast();
            }
            deque.offerLast(i);
            while(!deque.isEmpty() && i - deque.peekFirst() + 1 > k){
                deque.pollFirst();
            }
            ret[i - k + 1] = nums[deque.peekFirst()]; 
        }
        return ret;
    }
}

4.4 解题思路

  1. 使用双端队列解决问题,队列存放元素的下标。
  2. 先遍历前面k个元素,如果队列非空,并且当前的元素大于等于队尾的下标所对应的元素,则删除该元素(因为当前遍历的位置是滑动窗口末尾的元素,如果之前的元素不如当前元素值大,那么滑动窗口的最大值一定不是之前的元素)。之后将当前元素的下标存放进入队列的尾部。
  3. 结果数组第一位数即为队首元素。
  4. 之后从数组的第k位遍历到最后一位,前面的操作与2中操作一致,之后要对队首进行处理,如果队首的下标在当前滑动窗口的左边,则要删除队首元素,之后将滑动窗口内最大值(即为队首元素对应的元素)赋值给结果数组。

5. 最小覆盖子串

5.1 题目链接

点击跳转到题目位置

5.2 题目描述

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

提示:

  • m == s.length
  • n == t.length
  • 1 <= m, n <= 105
  • s 和 t 由英文字母组成

5.3 解题代码

class Solution {
    public String minWindow(String s, String t) {
        HashMap<Character, Integer> hash = new HashMap<>();
        int left = 0;
        int right = -1;
        int m = s.length();
        int n = t.length();
        int idx = n;
        int min_len = m + 1;
        int ans = -1;
        for(int i = 0; i < n; ++i){
            hash.put(t.charAt(i), hash.getOrDefault(t.charAt(i), 0) + 1);
        }
        while(right < m - 1){
            right++;
            char ch = s.charAt(right);
            if(hash.containsKey(ch)){
                if(hash.get(ch) > 0){
                    idx--;
                }
                hash.put(ch, hash.getOrDefault(ch, 0) - 1);
                if(idx == 0){
                    while(left <= right){
                        if(right - left + 1 < min_len){
                            min_len = right - left + 1;
                            ans = left;
                        }     
                        char ch1 = s.charAt(left);
                        left++;
                        if(hash.containsKey(ch1)){
                            hash.put(ch1, hash.getOrDefault(ch1, 0) + 1);
                            if(hash.get(ch1) > 0){
                                idx++;
                                break;
                            } 
                        }
                    }
                }
            }
        }
        return ans == -1 ? "" : s.substring(ans, ans + min_len);
    }
}

5.4 解题思路

  1. 标准的滑动窗口+哈希表
  2. 首先先用哈希表统计t中每种字符的长度,然后用一个标记idx用来判断窗口中包含t中的多少个元素。
  3. 右端移动,直到idx减少为0的时候移动左端,在移动前,先记录当前窗口大小,如果小于min_len,记录当前左端,并且更新min_len,移动左端,直到移动后的idx大于0.
  4. 移动窗口时,变化的是哈希表中对应存在字符的大小,如果减少到0后继续减少,idx不减少,否则idx会做相应的减少。

http://www.niftyadmin.cn/n/5861511.html

相关文章

【学习笔记】Cadence电子设计全流程(二)原理图库的创建与设计(8-15)

【学习笔记】Cadence电子设计全流程&#xff08;二&#xff09;原理图库的创建与设计&#xff08;下&#xff09; 2.8 Cadence 软件自带元件库2.9 原理图元器件关联PCB2.10 原理图元器件库的移植2.11 已有原理图输出元器件库2.12 原理图设计中调用元器件库2.13 原理图元器件库关…

SuperMap GIS基础产品FAQ集锦(20250217)

一、SuperMap iServer 问题1&#xff1a;GPA算子是否有相关文档? 11.1.1 【解决办法】该功能算子可参考帮助文档&#xff1a;https://help.supermap.com/iServer/Server_Service_Management/Geoprocessing/GPFun/FunctionDescription/FunctionMD/GeoprocessingFunctionMD.z…

2024年国赛高教杯数学建模A题板凳龙闹元宵解题全过程文档及程序

2024年国赛高教杯数学建模 A题 板凳龙闹元宵 原题再现 “板凳龙”&#xff0c;又称“盘龙”&#xff0c;是浙闽地区的传统地方民俗文化活动。人们将少则几十条&#xff0c;多则上百条的板凳首尾相连&#xff0c;形成蜿蜒曲折的板凳龙。盘龙时&#xff0c;龙头在前领头&#x…

VMware虚拟机打不开Ubuntu22.04,是否从库中移出Ubuntu_22.04_bak_1 64位.vmx 解决方法

VMware虚拟机打不开Ubuntu22.04&#xff0c;是否从库中移出Ubuntu_22.04_bak_1 64位.vmx 解决方法 解决方法

【git】工作流实战:从本地仓库到远程仓库,git pull 与git rebase使用讲解,案例解析

Git 工作流实战&#xff1a;从本地仓库到远程仓库 将代码从本地仓库推送到远程仓库&#xff0c;并模拟公司团队协作的场景。 如果还没有连接远程仓库可以注册一下Gitee https://gitee.com/ 新建仓库复制https git init git remote add origin 粘贴https 一、推送代码到…

LeetCode 热题 100_搜索插入位置(63_35_简单_C++)(二分查找)(”>>“ 与 “/” 对比)

LeetCode 热题 100_搜索插入位置&#xff08;63_35&#xff09; 题目描述&#xff1a;输入输出样例&#xff1a;题解&#xff1a;解题思路&#xff1a;思路一&#xff08;二分查找&#xff09;&#xff1a; 代码实现代码实现&#xff08;思路一&#xff08;二分查找&#xff09…

2025年2月一区SCI-海市蜃楼搜索优化算法Mirage search optimization-附Matlab免费代码

引言 本期介绍了一种基于海市蜃楼物理原理的元启发式优化算法——海市蜃楼搜索优化算法Mirage search optimization&#xff0c;MSO。该算法于2025年2月在线发表在JCR 一区、中科院2区SCI期刊 Advances in Engineering Software 海市蜃楼是一种常见的物理现象。海市蜃楼的形成…

视觉分析之边缘检测算法

9.1 Roberts算子 Roberts算子又称为交叉微分算法&#xff0c;是基于交叉差分的梯度算法&#xff0c;通过局部差分计算检测边缘线条。 常用来处理具有陡峭的低噪声图像&#xff0c;当图像边缘接近于正45度或负45度时&#xff0c;该算法处理效果更理想。 其缺点是对边缘的定位…