【图解算法】- 异位词问题:双指针+哈希表

news2025/1/9 1:09:26

  一 - 前言

介绍:大家好啊,我是hitzaki辰。

社区:(完全免费、欢迎加入)日常打卡、学习交流、资源共享的知识星球。

自媒体:我会在b站/抖音更新视频讲解 或 一些纯技术外的分享,账号同名:hitzaki辰。

正文开始,抓紧上车!


二 - 异位词问题概述

1 - 异位词是什么

1)比如 abc 和 bca就是一个异构词

2)异构词的简单判断:

(1)长度相等

(2)每个字母的数量都相等

2 - 判断异位词

对于需要比较的字符串s和t,使用哈希表可以很方便的判断异位词,维护1个count和一个哈希表

1)关键代码1解读 - 迭代s串

对字符串s的所有字符都进行哈希,此时map对应每个字符的数量,count代表字符的种类。

Map<Character, Integer> map = new HashMap<>();
int count = 0;
for(int i=0; i<p.length(); i++){
    Integer temp = map.get(p.charAt(i));
    map.put(p.charAt(i), temp==null? 1: temp+1);
    if(temp==null) count++;
}

比如aabc对应的map和count迭代过程为:

2)关键代码2解读 - 迭代t串:(不同的题,我们迭代的方式不同。)

获取当前t.charAt(i),

(1)若map中没有对应key,说明不是异位词

(2)若有key,将对应value-1,若减为0,则将count-1。

(3)若有key,且对应value已经等于0,说明不是异位词。

最后判断count是否为0,若为0说明是异位词。

以aaba为例:

3 - 根据题干优化

如果题干说只有小写或大写字母这种情况,即固定了出现可能的集合,则我们可以使用一个数组代替哈希表

s串每次迭代只需要这样:++count[s.charAt(i) - 'a'];

三 - 例题1:找到字符串所有字母异位词

题目索引:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

给定两个字符串 sp,找到 s 中所有 p异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

1 - 使用哈希表题解:详细注解

class Solution {

  public List<Integer> findAnagrams(String s, String p) {

​    Map<Character, Integer> map = new HashMap<>();

​    int count = 0;

​    List<Integer> result = new ArrayList<>();

​    for(int i=0; i<p.length(); i++){

​      Integer temp = map.get(p.charAt(i));

​      map.put(p.charAt(i), temp==null? 1: temp+1);

​      if(temp==null) count++;

​    }

​    int p1=0, p2=0;

​    boolean flag;

​    while(p2<s.length()){

​      // 迭代p2

​      Integer temp2 = map.get(s.charAt(p2));

​      if(temp2==null){ // 包含p2的都不可能,因此结束

​        flag = false;

​      }else{

​        flag = true;

​        map.put(s.charAt(p2), temp2-1);

​        if(temp2==1)count--;

​      }

​      p2++;

​      

​      // 迭代p1, 根据p2情况进行迭代

​      // 1.若p2存在, 则当p2-p1==p.length()时才进入

​      // 若p2不存在, 则迭代至p1==p2

​      while(flag? p2-p1==p.length(): p1<p2-1){ // 只有p2-1时有null判断

​        if(count==0)result.add(p1);

​        // 将p1位置给去除

​        Integer temp1 = map.get(s.charAt(p1)); 

​        if(temp1==0)count++;

​        map.put(s.charAt(p1), temp1+1);

​        p1++;

​      }

​      if(!flag)p1++; // p1=p2-1时候一定为null, 跳过

​    } // 主迭代结束

​    return result;

  }

}

2 - 使用数组题解:注解

class Solution {

  public List<Integer> findAnagrams(String s, String p) {

​    int sLen = s.length(), pLen = p.length();



​    if (sLen < pLen) {

​      return new ArrayList<Integer>();

​    }



​    List<Integer> ans = new ArrayList<Integer>();

​    int[] count = new int[26];

​    for (int i = 0; i < pLen; ++i) {

​      ++count[s.charAt(i) - 'a'];

​      --count[p.charAt(i) - 'a'];

​    }



​    int differ = 0;

​    for (int j = 0; j < 26; ++j) {

​      if (count[j] != 0) {

​        ++differ;

​      }

​    }



​    if (differ == 0) {

​      ans.add(0);

​    }



​    for (int i = 0; i < sLen - pLen; ++i) {

​      if (count[s.charAt(i) - 'a'] == 1) {  // 窗口中字母 s[i] 的数量与字符串 p 中的数量从不同变得相同

​        --differ;

​      } else if (count[s.charAt(i) - 'a'] == 0) {  // 窗口中字母 s[i] 的数量与字符串 p 中的数量从相同变得不同

​        ++differ;

​      }

​      --count[s.charAt(i) - 'a'];

​      if (count[s.charAt(i + pLen) - 'a'] == -1) {  // 窗口中字母 s[i+pLen] 的数量与字符串 p 中的数量从不同变得相同

​        --differ;

​      } else if (count[s.charAt(i + pLen) - 'a'] == 0) {  // 窗口中字母 s[i+pLen] 的数量与字符串 p 中的数量从相同变得不同

​        ++differ;

​      }

​      ++count[s.charAt(i + pLen) - 'a'];

​      

​      if (differ == 0) {

​        ans.add(i + 1);

​      }

​    }



​    return ans;

  }

}

四 - 例题2:最小覆盖子串

题目索引:https://leetcode.cn/problems/minimum-window-substring/description/

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

1 - 思路

例子:s = "ADOBECODEBANC", t = "ABC"

使用双指针

(1)左指针用来将map和count恢复

(2)右指针用来将map对应的value减一,并改变count

当count=0时,说明此时符合条件,则将此时的子串记录下来。

2 - 题解:详细注解

维护一个数量count和map, 先迭代t将map填充,然后让count = map.size

(1)p2遍历到的如果在map里就将map里对应元素-1, 如果刚好减到0就count-1

(2)如果count==0, 则开始遍历p1,

  每次让p1对应到map的元素+1, 每次迭代判断长度, 若小于min则更新

class Solution {
    public static String minWindow(String s, String t) {
        Map<Character, Integer> map = new HashMap<>();
        int min=Integer.MAX_VALUE, index=0,  count;
        Integer temp;
        for(int i=0; i<t.length(); i++){
            temp = map.get(t.charAt(i));
            map.put(t.charAt(i), temp==null? 1: temp+1);
        }
        count = map.size();
        int p1=0, p2=0;
        for(;p2<s.length();p2++){
            // 添加p2位置
            temp = map.get(s.charAt(p2));
            if(temp==null)continue;
            // 如果为1说明减完p2元素会归0, 则count变化
            map.put(s.charAt(p2), temp-1);
            if(temp==1) count--;
            // 迭代p1
            while(count==0){
                if(p2-p1+1<min) {
                    min = p2-p1+1;
                    index = p1;
                }
                // 去掉当前p1的元素
                temp = map.get(s.charAt(p1));
                p1++;
                if(temp==null)continue;
                map.put(s.charAt(p1-1), temp+1);
                if(temp==0) count++;
            }
        }
        if(min == Integer.MAX_VALUE)return "";
        return s.substring(index, index+min);
    }
}

五 - 结尾

感谢你看到这里,如果感觉内容不错的话请点赞支持一下!

如果小伙伴对我的讲解有疑问,欢迎评论区讨论。

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

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

相关文章

【Synopsys Bug记录】DC综合报错(显示warning:Unable to resolve reference)

文章目录 一、问题描述二、问题所在三、问题解决总结4.1 Warning的产生4.2 代码风格4.3 网表正确性 一、问题描述 在综合一个SOC时&#xff0c;发现综合后的门级网表文件缺少了apb系统下的子模块的网表。该SOC已经成功在FPGA上运行了&#xff0c;按理说在设计上是没有问题的。在…

Android平台 - APP备案

今年因 工业和信息化部 要求&#xff0c;Andorid各大厂商陆续发出通知&#xff0c;需要各应用公司及时进行app备案&#xff0c;如过期未进行备案则会被陆续下架&#xff01; 正好在统计Andorid各平台对于app备案时间节点要求&#xff0c;故此予以总结&#xff08;一切均已平台为…

oracle21c报错 【ORA-65096: 公用用户名或角色名无效】

1.数据库版本 oracle21c 2.问题提示 创建用户提示【ORA-65096: 公用用户名或角色名无效】 create user 自定义用户名 identified by 密码;--例:用户为test1&#xff0c;密码为123456 create user test1 identified by 123456;三.解决办法及结果 oracle11g之后的版本&#xff…

【从入门到起飞】JavaSE—IO工具包(Commons-io,Hutool) (2)

&#x1f38a;专栏【JavaSE】 &#x1f354;喜欢的诗句&#xff1a;天行健&#xff0c;君子以自强不息。 &#x1f386;音乐分享【如愿】 &#x1f384;欢迎并且感谢大家指出小吉的问题&#x1f970; 文章目录 &#x1f33a;工具包Commons-io⭐使用步骤&#x1f6f8;新建一个文…

Java编程中,使用时间戳机制实现增量更新的示例

一、需求 课程下可以创建多个讲次&#xff0c;然后分享出去。 在没有更新分享前&#xff0c;通过分享链接看到的课程及讲次详情是快照。课程制作者可以继续修改调整自己的课程&#xff0c;对分享用户是不可见。 当制作者完成修改后&#xff0c;更新分享&#xff0c;让用户看到…

ALlegro怎么恢复到初始操作界面?

1.View 2.UI Settings 3.Reset UI To Default

USART(1)

什么是USART 单片机上有的许多的外设 单片机通过这些外设实现特殊的功能 如果单片机想要和蓝牙模块实现数据的传输那么就也需要单片机有串口模块来和蓝牙模块的串口进行连接 相互传输数据 在单片机上的串口就叫USART USART就是单片机上的外设 来实现串口之间的通信功能 USART名…

ROS服务(Service)通信:通信模型、Hello World与拓展

服务通讯是基于请求响应模式的&#xff0c;是一种应答机制。 用于偶然的、对时时性有要求、有一定逻辑处理需求的数据传输场景。 一、服务通讯模型 服务是一种双向通讯方式&#xff0c;它通过请求和应答的方式传递消息&#xff0c;该模型涉及到三个角色&#xff1a; Master…

74基于matlab的PSO-ELM的多输入,单输出结果预测,输出训练集和测试机预测结果及误差。

基于matlab的PSO-ELM的多输入&#xff0c;单输出结果预测&#xff0c;输出训练集和测试机预测结果及误差&#xff0c;适应度值。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 74matlabPSO-ELM多输入单输出 (xiaohongshu.com)

Redis实战篇(1)

实战篇Redis 短信登录 这一块我们会使用redis共享session来实现 商户查询缓存 通过本章节&#xff0c;我们会理解缓存击穿&#xff0c;缓存穿透&#xff0c;缓存雪崩等问题&#xff0c;让小伙伴的对于这些概念的理解不仅仅是停留在概念上&#xff0c;更是能在代码中看到对应…

AMEYA360:罗姆旗下蓝碧石面向电动汽车开发出AVAS专用的语音合成LSI

罗姆集团旗下的蓝碧石科技株式会社(以下简称“蓝碧石科技”)面向电动汽车(xEV)开发出AVAS(车辆接近报警系统)专用的语音合成LSI“ML22120xx”(ML22120TB、ML22120GP)。 在推动实现碳中和(无碳)社会的进程中&#xff0c;混合动力汽车和纯电动汽车(EV)的数量不断增加。由于这些车…

Flutter笔记: 在Flutter应用中使用SQLite数据库

Flutter笔记 在Flutter应用中使用SQLite数据库&#xff08;基于sqflite&#xff09; 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/q…

人工智能引领环境保护的新浪潮:技术应用及其影响

在全球范围内&#xff0c;环境保护已经成为一个迫切的话题。随着人工智能技术的发展&#xff0c;它开始在环境保护领域扮演越来越重要的角色。AI不仅能够帮助更有效地监测环境变化&#xff0c;还能提出解决方案来应对环境问题。 污染监测与控制&#xff1a; AI系统可以分析来自…

【C语言】深入解开指针(三)

&#x1f308;write in front :&#x1f50d;个人主页 &#xff1a; 啊森要自信的主页 真正相信奇迹的家伙&#xff0c;本身和奇迹一样了不起啊&#xff01; 欢迎大家关注&#x1f50d;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;>希望看完我的文章对你有小小的帮助&#x…

企业云盘:企业文件数据存储与共享的全面解决方案

企业云盘为企业的文件数据的存储与管理提供了一种安全、高效又便捷的解决方案。在企业文件数据存储管理上&#xff0c;企业云盘有什么优势吗&#xff1f;本文将重点分析企业云盘的优点和好处&#xff01; 一、安全性 对于企业文件数据管理工具&#xff0c;安全是首位。与个人…

【源码系列】短剧系统开发国际版短剧系统软件平台介绍

系统介绍 短剧是一种快节奏、紧凑、有趣的戏剧形式&#xff0c;通过短时间的精彩表演&#xff0c;向观众传递故事的情感和思考。它以其独特的形式和魅力&#xff0c;吸引着观众的关注&#xff0c;成为了当代戏剧娱乐中不可或缺的一部分。短剧每一集都是一个小故事&#xff0c;…

【Java 进阶篇】深入浅出:JQuery 事件绑定的奇妙世界

在前端的世界里&#xff0c;事件是不可或缺的一部分。用户的点击、输入、滚动等行为都触发着各种事件&#xff0c;而如何在代码中捕捉并处理这些事件是每位前端开发者必须掌握的技能之一。本文将带你深入浅出&#xff0c;探索 JQuery 中的事件绑定&#xff0c;为你揭开这个奇妙…

IIC总线概述和通信时序代码详细图文解析

IIC总线 1 IIC总线概述 I2C总线两线制包括&#xff1a;串行数据SDA&#xff08;Serial Data&#xff09;、串行时钟SCL&#xff08;Serial Clock&#xff09;。总线必须由主机&#xff08;通常为微控制器&#xff09;控制&#xff0c;主机产生串行时钟&#xff08;SCL&#x…

【漏洞复现】用友移动管理系统文件上传

漏洞描述 用友移动系统管理旧版本uploadApk接口存在任意文件上传&#xff0c;攻击者可在无需登录的情况下上传恶意文件&#xff0c;执行任意命令 免责声明 技术文章仅供参考&#xff0c;任何个人和组织使用网络应当遵守宪法法律&#xff0c;遵守公共秩序&#xff0c;尊重社…

基于模拟退火算法优化概率神经网络PNN的分类预测 - 附代码

基于模拟退火算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于模拟退火算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于模拟退火优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…