LeetCode热题100(Java)(3)滑动窗口

本章包括的题目有:

3. 无重复字符的最长子串 - 力扣(LeetCode)

438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

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

思路解析:

要在一个字符串中找出最长的不含重复字符的子串,只需维护一个内部无重复的"窗口",在遍历过程中不断扩展并调整这个窗口,同时记录它曾经达到的最大长度。由于字符集有限(题目使用标准 ASCII,共 128 个),可以用一个长度为 128 的计数数组来快速判断当前窗口内某个字符是否重复出现。

算法使用左右指针 l 和 r 表示窗口的边界。一开始两者都在起始位置,计数数组全为零。右指针 r 依次向右移动,每次将新进入窗口的字符 s[r] 的计数加 1。如果该字符的计数超过 1,说明这个字符在窗口内重复了(由于只有新加入的字符可能造成重复),此时就不断右移左指针 l,并把离开窗口的字符计数减 1,直到该重复字符的计数降回 1,窗口重新成为无重复子串。每得到一个无重复的窗口,就用它的长度 r - l + 1 更新历史最大值 ret。当右指针遍历完整个字符串,ret 就是最长无重复子串的长度。

代码实现:

java 复制代码
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int ret = 0;
        int len = s.length();
        int l = 0,r = 0;
        int[] arr = new int[128];
        for (;r < len; r++) {
            arr[s.charAt(r)]++;
            while(arr[s.charAt(r)] > 1){
                arr[s.charAt(l)]--;
                l ++;
            }
            ret = Math.max(ret, (r - l + 1));
        }
        return ret;
    }
}

时间复杂度O(n)

空间复杂度O(1)

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

思路解析:

要在字符串 s 中找出所有与 p 互为字母异位词的子串的起始索引,只需用固定大小的滑动窗口在 s 上移动,并比较窗口内字符的频数与 p 的频数是否相同。由于题目只涉及小写字母,字符集大小固定为 26,可以用两个长度为 26 的整数数组分别记录 p 的字符频数和当前窗口的字符频数。

首先统计 p 中每个字母的出现次数,存入 count。然后初始化一个长度为 |p| 的窗口,但预先只将前 |p|-1 个字符的计数填入 count2,这样后续循环中就能自然地完成"加入右边界 → 比较 → 移除左边界"的固定节奏。若 count2 与 count 完全相等(使用 Arrays.equals 比较),说明当前窗口内的子串是 p 的一个字母异位词,把窗口的起始索引 i - |p| + 1 加入结果列表。比较完成后,将窗口左边界字符(同样是 i - |p| + 1)的计数减 1,为下一轮滑动做好准备。遍历结束,结果列表即为所有异位词子串的起始位置。

代码实现:

java 复制代码
class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        if(p.length() > s.length())return new ArrayList<>();
        List<Integer> ret = new ArrayList<>();
        char[] pp = p.toCharArray();
        int[] count = new int[26];
        for(char c: pp){
            count[c - 'a'] ++;
        }
        int[] count2 = new int[26];
        for (int i = 0; i < p.length() - 1; i++) {
            count2[s.charAt(i) - 'a']++;
        }
        for (int i = p.length() - 1; i < s.length(); i++) {
            count2[s.charAt(i) - 'a']++;
            if(Arrays.equals(count,count2))ret.add(i - p.length() + 1);
            count2[s.charAt(i - p.length() + 1) - 'a'] --;
        }
        return ret;
    }
}

补充:Arrays.equals(count,count2) 可以比较两个数组是否相同,但是 count.equals(count2) 只能比较两者的内存地址(引用)

时间复杂度O(n)

空间复杂度O(1)

上一章:

LeetCode热题100(Java)(2)双指针-CSDN博客

相关推荐
Aaron158819 分钟前
RFSOC+VU13P/VU9P+GPU多通道同步一体化解决方案
人工智能·嵌入式硬件·算法·matlab·fpga开发·硬件架构·基带工程
淡海水40 分钟前
ComfyUI全面掌握-知识点详解——基础示例:文生图与图生图实操(参数+案例)
大数据·人工智能·算法·comfyui
05候补工程师44 分钟前
【硬核干货】用“算法”思维袭英语新题型:集合逆清晰除与降维打击解题法
经验分享·笔记·考研·算法·学习方法
刀法如飞1 小时前
Palantir Ontology 数据结构分析,与ER/OOP/DDD有什么区别?
人工智能·算法·架构
白藏y1 小时前
【数据结构】简单选择排序
数据结构·算法·排序算法
信奥胡老师1 小时前
B3930 [GESP202312 五级] 烹饪问题
开发语言·数据结构·c++·学习·算法
paeamecium1 小时前
【PAT甲级真题】- Shortest Distance (20)
数据结构·c++·算法·pat考试·pat
aisifang001 小时前
GPT-Image2去偏见技术新突破
人工智能·算法·机器学习
吴可可1231 小时前
点在线上判定与多段线分割
算法·c#
吴可可1232 小时前
圆弧多段线离散化采样密度优化
算法·c#