当前位置: 首页 > article >正文

【算法刷题】leetcode hot 100 滑动窗口

文章目录

  • 3. 无重复字符的最长子串
  • 438. 找到字符串中所有字母异位词
  • 总结


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

在这里插入图片描述

  1. leetcode:https://leetcode.cn/problems/longest-substring-without-repeating-characters/?envType=study-plan-v2&envId=top-100-liked

  2. 滑动窗口

(1)右指针向右扩大窗口,直到不满足条件。
(2)左指针向右压缩窗口,直到满足条件。
(3)继续(1)-(2)操作,统计最大的窗口。

   public int lengthOfLongestSubstring(String s) {
        if (s == null || s.isEmpty()) {
            return 0;
        }
        int max = 0;
        int[] index = new int[128];
        int i = 0, j = 0;
        while (i <= j && j < s.length()) {
            if (index[s.charAt(j)] == 0) {
                index[s.charAt(j)]++;
                j++;
            }else {
                max = Math.max(max, j - i );
                index[s.charAt(i)]--;
                i++;
            }
        }

        max = Math.max(max, j - i );

        return max;
    }


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

在这里插入图片描述

  1. leetcode:https://leetcode.cn/problems/find-all-anagrams-in-a-string/description/?envType=study-plan-v2&envId=top-100-liked

  2. 开始的想法:先给字符串p排个序,然后遍历s,取当前下标开始的长度和p相等的字符串,排序,和排过序的p进行比较,相等就符合条件。显然这种解法可行,但效率太低。

   public List<Integer> findAnagrams(String s, String p) {
        List<Integer> ans = new ArrayList<>();
        char[] ss = s.toCharArray();
        char[] ps = p.toCharArray();

        Arrays.sort(ps);

        for (int i = 0; i <= ss.length - ps.length; i++){
            char[] temp = s.substring(i, i + ps.length).toCharArray();
            Arrays.sort(temp);
            if (Arrays.equals(ps, temp)){
                ans.add(i);
            }
        }


        return ans;
    }

  1. 滑动窗口:

初始化计数器

  • 使用数组 pCount 记录字符串 p 中每个字符的频率。
  • 使用数组 sCount 记录当前窗口中字符的频率。

滑动窗口

  • 遍历字符串 s,逐步更新窗口。
  • 当窗口长度超过 p 的长度时,移除窗口左端的字符。

比较频率数组

  • 每次更新窗口后,比较 sCountpCount 是否相等。
  • 如果相等,则说明窗口中的子字符串是异位词,记录起始索引。
    public List<Integer> findAnagrams2(String s, String p) {
        List<Integer> ans = new ArrayList<>();
        int[] c1 = new int[26];
        int[] c2 = new int[26];
        for (char c : p.toCharArray()) {
            c1[c - 'a']++;
        }

        for (int i = 0; i < s.length(); i++) {
            c2[s.charAt(i) - 'a']++;

            // 移除窗口外的元素
            if (i >= p.length()) {
                c2[s.charAt(i-p.length()) - 'a']--;
            }

            if (Arrays.equals(c1, c2)) {
                ans.add(i-p.length()+1);
            }
        }

        return ans;

    }


总结

滑动窗口是一种常见的算法技巧,主要用于解决字符串、数组等线性数据结构中的子区间问题。通过维护一个动态更新的窗口(子区间),可以高效地找到问题的解。滑动窗口适合解决的问题通常具有连续性或者需要频繁更新子区间的性质。

滑动窗口的基本思想

  1. 定义一个窗口:
    • 通常用两个指针(leftright)来定义窗口的左右边界。
    • 窗口可以扩展(右边界向右移动)或收缩(左边界向右移动)。
  2. 移动窗口:
    • 根据问题要求,逐步移动右边界来扩展窗口。
    • 根据条件判断是否需要收缩左边界。
  3. 更新答案:
    • 在窗口满足某些条件时,更新答案(如最大值、最小值、计数等)。
  4. 窗口内数据结构:
    • 为了高效维护窗口状态,通常需要使用额外的数据结构(如数组、HashMapHashSet)来记录窗口内的数据。
int left = 0; // 窗口左边界
int right = 0; // 窗口右边界

while (right < s.length()) { // 遍历字符串/数组
    // 扩展窗口(添加右边的元素)
    char c = s.charAt(right);
    right++;
    
    // 根据问题更新窗口内状态(如计数、频率等)
    
    while (窗口不满足条件) {
        // 收缩窗口(移除左边的元素)
        char d = s.charAt(left);
        left++;
        
        // 更新窗口内状态
    }
    
    // 如果窗口满足条件,更新答案
}



http://www.kler.cn/a/488132.html

相关文章:

  • Fastapi + vue3 自动化测试平台(1)--开篇
  • 基于html5实现音乐录音播放动画源码
  • 运放输入偏置电流详解
  • Linux下文件重定向
  • nginx 日志规范化意义及实现!
  • 33.3K 的Freqtrade:开启加密货币自动化交易之旅
  • 高斯函数Gaussian绘制matlab
  • 在FreeBSD、Windows、Ubuntu24三种平台下安装Racket
  • 【数据结构】树的定义
  • ElasticSearch | Elasticsearch与Kibana页面查询语句实践
  • flowable mysql 表名大小写问题
  • 【经典神经网络架构解析篇】【1】LeNet网络详解:模型结构解析、优点、实现代码
  • Android 系统签名 keytool-importkeypair
  • 解决anaconda prompt找不到的情况
  • STM32F767+LWIP+CubeMX配置中断模式
  • 【C++经典例题】求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句
  • 【LeetCode】每日一题 2024_1_10 统计重新排列后包含另一个字符串的子字符串数目 II(滑动窗口)
  • 10-pyecharts绘图
  • Spring bean的生命周期和扩展
  • 践行“金融为民” 平安养老险迎来理赔新篇章
  • 使用Postman实现API自动化测试
  • 【股票数据API接口02】如何获取股票历史交易数据之Python、Java等多种主流语言实例代码演示通过股票数据接口获取数据
  • 基于QT和C++的实时日期和时间显示
  • Vue2:el-table中的文字根据内容改变颜色
  • Spring——自动装配
  • C++笔记之`size_t`辨析