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博客

相关推荐
8Qi834 分钟前
LeetCode 213:打家劫舍 II(House Robber II)—— 题解 ✅
算法·leetcode·职场和发展·动态规划
三品吉他手会点灯42 分钟前
C语言学习笔记 - 44.运算符和表达式 - 运算符2 - 除法与取余运算符
c语言·开发语言·笔记·算法
乐迪信息1 小时前
乐迪信息:AI算法盒子实时识别船舶烟雾与火焰异常
大数据·人工智能·算法·安全·目标跟踪
J-Tony111 小时前
【JVM】根可达算法
jvm·算法
艾iYYY1 小时前
string 类的模拟实现
android·服务器·c语言·c++·算法
Lsk_Smion2 小时前
力扣实训 _ [75].颜色分类 _ 杨辉三角
数据结构·算法·leetcode
jidaowansui2 小时前
P11375 [GESP202412 六级] 树上游走
数据结构·算法
hai3152475433 小时前
FlashAttention C语言(C++)实现(展示版)
c语言·开发语言·c++·人工智能·算法
林爷万福3 小时前
光谱数据预处理:基线校正、平滑去噪实战
人工智能·算法