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

本章包括的题目有:

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

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

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

思路解析:

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

算法使用左右指针 l 和 r 表示窗口的边界。一开始两者都在起始位置,计数数组全为零。右指针 r 依次向右移动,每次将新进入窗口的字符 sr 的计数加 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博客

相关推荐
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼3 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark3 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her13 天前
并查集-听课笔记
笔记·算法·并查集
码流子3 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven3 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark3 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218613 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法