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

  一 - 前言

介绍:大家好啊,我是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--;// 迭代p1while(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.hqwc.cn/news/188376.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统(CentOS7)上安装MYSQL8.x

Linux系统是CentOS7版本&#xff0c;今天在新电脑上安装MYSQL&#xff0c;跟着网上的文章&#xff0c;尝试了好几次&#xff0c;都是启动失败&#xff0c;删了安&#xff0c;安了删&#xff0c;搞了一下午&#xff0c;头昏脑胀&#xff0c;网上的一些文章太乱了&#xff0c;每种…

flink中配置Rockdb的重要配置项

背景 由于我们在flink中使用了状态比较大&#xff0c;无法完全把状态数据存放到tm的堆内存中&#xff0c;所以我们选择了把状态存放到rockdb上&#xff0c;也就是使用rockdb作为状态后端存储,本文就是简单记录下使用rockdb状态后端存储的几个重要的配置项 使用rockdb状态后端…

geoserver点聚合样式sld

【第六章 WebGIS】geoserver生成点聚合效果 - 知乎 需要WPS插件&#xff0c;注意版本要对应 GeoServer&#xff0c;加压缩后的jar包放到geoserver的lib目录下&#xff0c;重启geoserver。 原始默认样式 聚合sld样式 <?xml version"1.0" encoding"ISO-8859…

基于51单片机步进电机节拍步数正反转LCD1602显示( proteus仿真+程序+原理图+设计报告+讲解视频)

基于51单片机步进电机节拍步数正反转LCD1602显示 &#x1f4d1;1. 主要功能&#xff1a;&#x1f4d1;2. 讲解视频&#xff1a;&#x1f4d1;3. 仿真&#x1f4d1;4. 程序代码&#x1f4d1;5. 设计报告&#x1f4d1;6. 设计资料内容清单&&下载链接&#x1f4d1;[资料下…

Appium移动自动化测试--安装Appium

Appium 自动化测试是很早之前就想学习和研究的技术了&#xff0c;可是一直抽不出一块完整的时间来做这件事儿。现在终于有了。 反观各种互联网的招聘移动测试成了主流&#xff0c;如果再不去学习移动自动化测试技术将会被淘汰。 web自动化测试的路线是这样的&#xff1a;编程语…

使用Microsoft Dynamics AX 2012 - 2. 入门:导航和常规选项

Microsoft Dynamics AX的核心原则之一是为习惯于Microsoft软件的用户提供熟悉的外观和感觉。然而&#xff0c;业务软件必须适应业务流程&#xff0c;这可能相当复杂。 用户界面和常见任务 在我们开始进行业务流程和案例研究之前&#xff0c;我们想了解一下本章中的常见功能。…

“轻松实现文件复制备份,自动编号轻松管理

在日常工作中&#xff0c;我们经常需要复制文件到另一个文件夹进行备份或整理。然而&#xff0c;手动复制粘贴不仅效率低下&#xff0c;还容易出错。为了解决这个问题&#xff0c;我们推出了一款全新的文件工具——【文件批量改名高手】&#xff0c;让你轻松搞定文件复制备份&a…

基于SSM+Vue的校园共享单车管理系统

基于SSMVue的校园共享单车管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringMyBatisSpringMVC工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 登录界面 管理员界面 用户界面 摘要 随着城市交通的不断发展和人们出…

黑五来袭,如何利用海外代理进行助力

黑五作为下半年年度尤为重要的一个节日&#xff0c;是各大商家的必争之地&#xff0c;那么海外代理是如何帮助跨境商家做好店铺管理和营销呢&#xff1f; 为什么跨境人都关注海外代理&#xff0c;下面我们来进行介绍。 一、什么是海外代理 海外代理就是我们所说的&#xff1…

内存模型以及如何判定对象已死问题

1.展示堆内存溢出 设置堆的内存大小为10M&#xff0c;最大的堆内存为10M&#xff0c;这两个参数最好一致&#xff0c;即便最大内存设置为1G&#xff0c;很有可能也分配不到1G。 -Xmx10M -Xms10M 一直往list放东西 public class T1 {public static void main(String[] args) …

全国临床遗传学及遗传咨询培训在湘举行,为18省培训百名医师

全国临床遗传学及遗传咨询培训在湘举行 为18省培训百名医师 党的二十大报告中强调&#xff0c;要推进健康中国建设&#xff0c;开展孕育能力提升专项攻关。2023年11月13日&#xff0c;由湖南家辉遗传专科医院及多家医学协会联合主办的全国临床遗传学及遗传咨询培训在湖南长沙举…

【Java 进阶篇】揭秘 JQuery 广告显示与隐藏:打造令人惊艳的用户体验

在当今互联网时代&#xff0c;广告已经成为网页中不可忽视的一部分。然而&#xff0c;如何通过巧妙的交互设计&#xff0c;使广告既能吸引用户的眼球&#xff0c;又不会给用户带来干扰&#xff0c;成为了许多前端开发者需要思考的问题之一。在这篇博客中&#xff0c;我们将深入…