day1_slidingWindow

news2024/11/16 18:07:30

一、滑动窗口模板

// 注意:java 代码由 chatGPT🤖 根据我的 cpp 代码翻译,旨在帮助不同背景的读者理解算法逻辑。
// 本代码不保证正确性,仅供参考。如有疑惑,可以参照我写的 cpp 代码对比查看。

import java.util.HashMap;
import java.util.Map;

public class Main {
    /* 滑动窗口算法框架 */
    public static void slidingWindow(String s) {
        // 用合适的数据结构记录窗口中的数据,根据具体场景变通
        // 比如说,我想记录窗口中元素出现的次数,就用 map
        // 我想记录窗口中的元素和,就用 int
        Map<Character, Integer> window = new HashMap<>();
        
        int left = 0, right = 0;
        while (right < s.length()) {
            // c 是将移入窗口的字符
            char c = s.charAt(right);
            window.put(c, window.getOrDefault(c, 0) + 1);
            // 增大窗口
            right++;
            // 进行窗口内数据的一系列更新
            // ...

            /*** debug 输出的位置 ***/
            // 注意在最终的解法代码中不要 print
            // 因为 IO 操作很耗时,可能导致超时
            System.out.printf("window: [%d, %d)\n", left, right);
            /********************/
            
            // 判断左侧窗口是否要收缩
            while (left < right && window needs shrink) {
                // d 是将移出窗口的字符
                char d = s.charAt(left);
                window.put(d, window.get(d) - 1);
                // 缩小窗口
                left++;
                // 进行窗口内数据的一系列更新
                // ...
            }
        }
    }

    public static void main(String[] args) {
        slidingWindow("your string here");
    }
}

在这里插入图片描述

背完模板后,还需要考虑什么?

1、什么时候应该移动 right 扩大窗口?窗口加入字符时,应该更新哪些数据?

2、什么时候窗口应该暂停扩大(满足了条件),开始移动 left 缩小窗口?从窗口移出字符时,应该更新哪些数据?

3、我们要的结果应该在扩大窗口时还是缩小窗口时进行更新?

如果一个字符进入窗口,应该增加 window 计数器;如果一个字符将移出窗口的时候,应该减少 window 计数器;当 valid 满足 need 时应该收缩窗口;应该在收缩窗口的时候更新最终结果。

1.最小覆盖子串
  1. s是长字符串,t是短字符串
  2. need.size() 是 t中 不同字符的种类数,同样的valid 每加1表示的是一个字符被满足,而不是某个字符的数量匹配上了一次
/**
 * 求字符串 s 中包含字符串 t 所有字符的最小子串
 * @param s 源字符串
 * @param t 给定字符串
 * @return 满足条件的最小子串
 */
public String minWindow(String s, String t) {
    // 用于记录需要的字符和窗口中的字符及其出现的次数
    Map<Character, Integer> need = new HashMap<>();
    Map<Character, Integer> window = new HashMap<>();
    // 统计 t 中各字符出现次数
    for (char c : t.toCharArray()) 
        need.put(c, need.getOrDefault(c, 0) + 1);

    int left = 0, right = 0;
    int valid = 0; // 窗口中满足需要的字符个数
    // 记录最小覆盖子串的起始索引及长度
    int start = 0, len = Integer.MAX_VALUE;
    while (right < s.length()) {
        // c 是将移入窗口的字符
        char c = s.charAt(right);
        // 扩大窗口
        right++;
        // 进行窗口内数据的一系列更新
        if (need.containsKey(c)) {
            window.put(c, window.getOrDefault(c, 0) + 1);
            if (window.get(c).equals(need.get(c)))
                valid++; // 只有当 window[c] 和 need[c] 对应的出现次数一致时,才能满足条件,valid 才能 +1
        }

        // 判断左侧窗口是否要收缩
        while (valid == need.size()) {
            // 更新最小覆盖子串
            if (right - left < len) {
                start = left;
                len = right - left;
            }
            // d 是将移出窗口的字符
            char d = s.charAt(left);
            // 缩小窗口
            left++;
            // 进行窗口内数据的一系列更新
            if (need.containsKey(d)) {
                if (window.get(d).equals(need.get(d)))
                    valid--; // 只有当 window[d] 内的出现次数和 need[d] 相等时,才能 -1
                window.put(d, window.get(d) - 1);
            }
        }
    }

    // 返回最小覆盖子串
    return len == Integer.MAX_VALUE ?
        "" : s.substring(start, start + len);
}

在这里插入图片描述

在Java中,对于对象类型(如Integer、String等),我们通常使用equals()方法来判断它们的值是否相等,而不是使用等号==。

原因是,等号 == 在比较对象类型时,比较的是对象的引用(内存地址),而不是对象的实际值。也就是说,使用 == 来比较两个对象,只有当它们引用同一个对象时,才会返回true。

然而,equals()方法被设计用来比较对象的值是否相等。对于String类型,equals()方法已经被重写,用于比较两个字符串的内容是否相等。对于Integer类型,equals()方法也被重写,用于比较两个整数值是否相等。

因此,如果我们想要比较两个对象的值是否相等,应该使用equals()方法。例如,使用s1.equals(s2)来比较两个字符串s1和s2的内容是否相等。

需要注意的是,有些对象类型(如Integer、Character等)具有自动拆装箱的功能,可以直接使用等号==进行比较。这是因为Java会自动将基本类型转换为对应的包装类型,以便进行比较。但是,对于其他对象类型,我们仍然应该使用equals()方法来确保正确的比较

2.字符串的排列
class Solution {
    public boolean checkInclusion(String s1, String s2) {
        HashMap<Character, Integer> need = new HashMap<>();
        HashMap<Character, Integer> window = new HashMap<>();
        for(int i = 0; i < s1.length(); i++){
            char c = s1.charAt(i);
            need.put(c, need.getOrDefault(c, 0) + 1);
        }

        int left = 0,right = 0;
        int valid = 0;
        while(right < s2.length()){
            char c = s2.charAt(right);
            right++;
            if(need.containsKey(c)){
                window.put(c, window.getOrDefault(c, 0) + 1);
                if(window.get(c).equals(need.get(c)))
                    valid++;
            }

            //判断左窗口是否要收缩
            while(right - left >= s1.length()){
                //在这里判断是否找到了合法的子串
                if(valid == need.size())
                    return true;
                char d = s2.charAt(left);
                left++;
                if(need.containsKey(d)){
                    if(window.get(d).equals(need.get(d)))
                    valid--;
                    window.put(d, window.getOrDefault(d, 0) - 1);
                }
            }
        }
        //未找到符合条件的子串
        return false;
    }
}

在这里插入图片描述

3.找出所有的字母异位词438
// 注意:java 代码由 chatGPT🤖 根据我的 cpp 代码翻译,旨在帮助不同背景的读者理解算法逻辑。
// 本代码不保证正确性,仅供参考。如有疑惑,可以参照我写的 cpp 代码对比查看。

public List<Integer> findAnagrams(String s, String t) {
    Map<Character, Integer> need = new HashMap<>();
    Map<Character, Integer> window = new HashMap<>();
    for (int i = 0; i < t.length(); i++) {
        char c = t.charAt(i);
        need.put(c, need.getOrDefault(c, 0) + 1);
    }

    int left = 0, right = 0;
    int valid = 0;
    List<Integer> res = new ArrayList<>(); // 记录结果
    while (right < s.length()) {
        char c = s.charAt(right);
        right++;
        // 进行窗口内数据的一系列更新
        if (need.containsKey(c)) {
            window.put(c, window.getOrDefault(c, 0) + 1);
            if (window.get(c).equals(need.get(c))) {
                valid++;
            }
        }
        // 判断左侧窗口是否要收缩
        while (right - left >= t.length()) {
            // 当窗口符合条件时,把起始索引加入 res
            if (valid == need.size()) {
                res.add(left);
            }
            char d = s.charAt(left);
            left++;
            // 进行窗口内数据的一系列更新
            if (need.containsKey(d)) {
                if (window.get(d).equals(need.get(d))) {
                    valid--;
                }
                window.put(d, window.get(d) - 1);
            }
        }
    }
    return res;
}

4.最长无重复子串
int lengthOfLongestSubstring(String s) {
    Map<Character, Integer> window = new HashMap<>();

    int left = 0, right = 0;
    int res = 0; // 记录结果
    while (right < s.length()) {
        char c = s.charAt(right);
        right++;
        // 进行窗口内数据的一系列更新
        window.put(c, window.getOrDefault(c, 0) + 1);
        // 判断左侧窗口是否要收缩
        while (window.get(c) > 1) {
            char d = s.charAt(left);
            left++;
            // 进行窗口内数据的一系列更新
            window.put(d, window.get(d) - 1);
        }
        // 在这里更新答案
        res = Math.max(res, right - left);
    }
    return res;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1658174.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mac YOLO V9推理测试

环境&#xff1a; Mac M1 (MacOS Sonoma 14.3.1) Python 3.11PyTorch 2.1.2 一、准备工作 工程及模型下载&#xff1a;​​​​​​​https://github.com/WongKinYiu/yolov9 git clone https://github.com/WongKinYiu/yolov9.git 克隆后安装相关依赖&#xff08;没啥依赖好装…

轮廓提取、矩形标记时,点的位置需要重标

在下图中的0&#xff0c;3&#xff0c;1&#xff0c;2位置如何变换成0&#xff0c;1&#xff0c;2&#xff0c;3 先显示结果&#xff1a; 变换之后图&#xff1a; 这边提供两种解决方案&#xff1a; 第一种&#xff1a;将坐标值相加求和&#xff0c;采用冒泡排序实现从小到大…

基于51单片机可调幅度频率波形信号发生器

基于51单片机可调幅度频率信号发生器( proteus仿真程序原理图报告讲解视频&#xff09; 1.主要功能&#xff1a; 基于51单片机的三角波信号发生器 1、幅值在0-5V可以通过按键调整&#xff0c;频率在0-50Hz,可以通过按键调整 2、通过LCD1602显示幅值和频率 3、使用示波器查…

postman介绍、安装、使用、功能特点、注意事项

Postman是一款流行的API开发工具&#xff0c;它提供了丰富的功能&#xff0c;包括创建、测试、调试和文档化API。本文将介绍Postman的安装、使用方法&#xff0c;以及其功能特点和注意事项。 1. 介绍 Postman是一款用于构建、测试和调试API的工具&#xff0c;它提供了用户友好的…

2. Linux 基本指令(上)|ls|pwd|cd|tree|touch|mkdir|rmdir|rm

前言 计算机软硬件体系结构 层状结构应用软件Word&#xff0c;Matlab操作系统Windows&#xff0c;Linux设备驱动声卡驱动硬件CPU&#xff0c;内存&#xff0c;磁盘&#xff0c;显示器&#xff0c;键盘 操作系统概念 操作系统 是一款进行软硬件资源管理的软件 例子 比如在学…

Q1保健品线上市场分析(三):牛初乳市场扩张,同比去年增长54%

近几年&#xff0c;牛初乳在多项科学研究支撑下&#xff0c;其卓越的“肠道免疫力”正得到越来越多的挖掘、验证和商业化尝试。因此&#xff0c;随着人们对健康饮食的重视&#xff0c;牛初乳产品的需求量也在逐年增加&#xff0c;市场潜力巨大。 根据鲸参谋数据显示&#xff0…

AI 资料汇总专栏

包含AI资料、大模型资料、AI最新行业发展 人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;是一门研究如何使计算机能够具备智能行为的科学与技术。它致力于开发出能够像人类一样思考、学习、理解和决策的计算机系统。自20世纪50年代以来&#xff…

C语言leetcode刷题笔记2

C语言leetcode刷题笔记2 第4题&#xff1a;283.移动零互换直接移动 第5题&#xff1a;122.买卖股票的最佳时机‖递归&#xff08;超时&#xff09;动态规划贪心算法 第6题&#xff1a;49.字母异位词分组优化 第4题&#xff1a;283.移动零 给定一个数组 nums&#xff0c;编写一…

100G ZR4 80KM光模块产品亮点有哪些

之前的文章我们介绍了100G ZR4 80KM光模块的产品特征以及技术原理等&#xff0c;那本期文章我们来了解一下易天第二代100G ZR4 80KM光模块的产品亮点。 首先我们通过下面这张表格以最直观的方式来了解第一代和第二代100G ZR4 80KM光模块在工作温度、功耗、FEC纠错等方面有哪些…

哪个可以下载视频素材?哪里有视频素材网站啊?

在这个视频内容日益重要的世界里&#xff0c;选择正确的可商用素材网站可以极大提升您的项目质量。下面是另一批国内外知名的视频素材网站&#xff0c;希望能为您的创作提供新的灵感。 1. 蛙学府 提供广泛的创意资产&#xff0c;包括高分辨率的视频素材。订阅后用户可无限次下…

VIsualGDB : 快速入门系列

《VisualGDB &#xff1a; 解决编码导致的编译错误》 《VisualGDB &#xff1a; 在windows上开发和调试Linux代码&#xff08;一&#xff09;》 《VisualGDB&#xff1a;为Linux项目添加系统依赖库》 《VisualGDB&#xff1a;Linux动态库项目创建、编译及库的使用》 《VisualGD…

点击导航栏选项后,导航栏高亮该选项

如图所示&#xff0c;点击“流浪猫客栈”时&#xff0c;会一直高亮显示&#xff0c;表示现在看的是这个选项的页面。 Cat.jsp上写&#xff1a; <!--header--> <jsp:include page"header.jsp"><jsp:param name"flag" value"3">…

中国科技大航海时代,“掘金”一带一路

文&#xff5c;白 鸽 编&#xff5c;王一粟 “这不就是90年代的内地吗&#xff1f;” 在深度考察完沙特市场后&#xff0c;华盛集团联合创始人兼CEO张霆对镜相工作室感慨道。 在张霆看来&#xff0c;沙特落后的基建&#xff08;意味着大量创新空间&#xff09;、刚刚开放…

邮件系统国产化,保障企业信息安全的重要举措

随着信息技术日益发展和成熟&#xff0c;企业信息化建设深入推进&#xff0c;企业信息化管理能力大幅提升&#xff0c;其中邮件系统在企业信息化建设中扮演着至关重要的角色。然而&#xff0c;长期以来&#xff0c;我国企业在邮件系统方面主要依赖于国外的产品&#xff0c;这不…

【Linux系统】进程控制

再次理解进程 进程&#xff1a;内核的相关管理数据结构(task_struct(进程控制块PCB)&#xff0c;mm_struct(地址空间)&#xff0c;页表) 代码和数据 那么如何理解进程具有独立性&#xff1f; 我们之前已经学习过进程控制块啊&#xff0c;地址空间啊&#xff0c;页表啊&…

Linux-笔记 修改开发板默认时区

1. 时区文件 使用命令date -R查看当前的默认时区&#xff0c;date - R命令会自动解析/etc/localtime 文件&#xff0c;而该文件又是指向“ /usr/share/zoneinfo/$主时区/$次时区 ”&#xff0c;当需要更改到指定的时区只要将/etc/localtime 文件软链接到 ”/usr/share/zoneinf…

c++ libtorch使用cmake建立

如果我们安装好pytorch&#xff0c;其实不一定一定要安装libtorch&#xff0c;默认都已经安装过了 1 进入pytorch conda env list conda activate pytorch 命令行下使用 python -c 来获取libtorch的基本信息&#xff0c; python -c "import torch;print(torch.utils.c…

1.基于python的单细胞数据预处理-质量控制

目录 质量控制过滤低质量细胞的指南双细胞过滤手动过滤低质量读数细胞自动过滤低质量读数细胞环境RNA校正 参考&#xff1a; [1] https://github.com/Starlitnightly/single_cell_tutorial [2] https://github.com/theislab/single-cell-best-practices 质量控制 原始的单细胞…

[C++核心编程-05]----C++类和对象之对象的初始化和清理

目录 引言 正文 01-构造函数和析构函数 ​02-构造函数的分类及调用 03-拷贝构造函数调用时机 04-构造函数调用规则 05-深拷贝与浅拷贝 06-初始化列表 07-静态成员变量 08-静态成员函数 …

vue3 - 150

目录 vue优势使用方式编写vue代码指令响应式数据其他 vue优势 功能全面生态好&#xff0c;语法简洁效率高&#xff0c;免去 DOM 操作苦&#xff0c;开发重任一肩挑&#xff01; 使用方式 1.通过cdn引入来将 Vue 应用到整个页面 2.或通过官方脚手架 create-vue来创建完整的v…