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

  一 - 前言

介绍:大家好啊,我是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);
    }
}

五 - 结尾

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第23天|669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树

JAVA代码编写 669. 修剪二叉搜索树 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果没有被移除&#x…

企业是否需要单独一套设备管理系统?

在现代企业中&#xff0c;设备管理是一个至关重要的环节。随着科技的不断进步和信息化的发展&#xff0c;企业对设备管理的要求也越来越高。为了提高设备管理的效率和准确性&#xff0c;许多企业开始考虑是否需要单独一套设备管理系统。本文将从设备管理系统的介绍、和其他系统…

腾讯云服务器怎么买便宜?腾讯云服务器优惠链接

现在&#xff0c;让我们一起探索如何在腾讯云服务器上购买便宜的云服务器吧&#xff01; 首先&#xff0c;我们来看看都有哪些便宜的腾讯云服务器值得我们入手吧&#xff01; 首先是轻量2核2G3M服务器&#xff0c;只需要一年88元就能轻松拥有&#xff0c;对于刚开始接触云服务…

linux查看pcie速率

先通过lspci命令查找pcie对应设备编号&#xff0c;如下图中为01:00.0 再通过以下命令查找上一步编号对应设备带宽信息&#xff0c;如下图中为8GT/s lspci -n -s 01:00.0 -vvv | grep --color Width

简单解决网页的验证码

翻到一个网站,展开需要验证码,而验证码需要关注微信公众号,懒得弄,所以有了这篇文章 首先,先看一下F12中的网络(Network),发现并没有使用网络动态验证 那么这个验证码必定是写在资源文件中的 在确定按钮上看到如下元素监听(Event Listeners) 进入打断点 成功断下 单步跟到…

数据库常见面试题

存储引擎 InnoDB&#xff08;默认&#xff09; 存储引擎的对比 MYISAM被MangoDB替代了 MEMORY被Redis替代了 索引 是一种高效获取数据的数据结构 索引结构 二叉树&#xff0c;红黑树&#xff08;都不合适&#xff09; B树 插入超过5个数&#xff0c;会从中间分裂 B树 …

苍穹外卖项目笔记(2)

1 Nginx 反向代理和负载均衡 1.1 概念 【Tips】可以看到前端请求地址和后端接口地址并不匹配&#xff0c;这里涉及到 nginx 反向代理 &#xff0c;就是将前端发送的动态请求由 nginx 转发到后端服务器 使用 nginx 作反向代理的好处&#xff1a; 提高访问速度&#xff08;在请…

时间序列预测中的4大类8种异常值检测方法(从根源上提高预测精度)

一、本文介绍 本文给大家带来的是时间序列预测中异常值检测&#xff0c;在我们的数据当中有一些异常值&#xff08;Outliers&#xff09;是指在数据集中与其他数据点显著不同的数据点。它们可能是一些极端值&#xff0c;与数据集中的大多数数据呈现明显的差异。异常值可能由于…

Linux系统下安装go

目录 下载go安装包解压包并安装添加环境变量验证是否安装成功 下载go安装包 官网地址&#xff1a;go 解压包并安装 复制好包的下载链接后使用下面命令进行安装&#xff1a; curl -O https://storage.googleapis.com/golang/go1.11.1.linux-amd64.tar.gz mkdir -p ~/installe…

结构体数组保存进二进制文件的简单做法

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> 最近面临这样一个需求&#xff1a;以比较节省存储空间的存储一组坐标点到文件&#xff0c;要求程序能够跨平台读写这种文件。思考了一下&#xff0c;比较…

Kafka学习笔记(一)

目录 第1章 Kafka概述1.1 消息队列&#xff08;Message Queue&#xff09;1.1.1 传统消息队列的应用场景1.1.2 消息队列的两种模式 1.2 定义 第2章 Kafka快速入门2.1 安装部署2.1.1 集群规划2.1.2 jar包下载2.1.3 集群部署 2.2 Kafka命令行操作 第3章 Kafka架构深入3.1 Kafka工…

23111704[含文档+PPT+源码等]计算机毕业设计springboot办公管理系统oa人力人事办公

文章目录 **软件开发环境及开发工具&#xff1a;****功能介绍&#xff1a;****实现&#xff1a;****代码片段&#xff1a;** 编程技术交流、源码分享、模板分享、网课教程 &#x1f427;裙&#xff1a;776871563 软件开发环境及开发工具&#xff1a; 前端技术&#xff1a;jsc…

实例解释遇到前端报错时如何排查问题

前端页面报错&#xff1a; 1、页面报错500&#xff0c;首先我们可以知道是服务端的问题&#xff0c;需要去看下服务端的报错信息&#xff1a; 2、首先我们查看下前端是否给后端传了id: 我们可以看到接口是把ID返回了&#xff0c;就需要再看下p_id是什么情况了。 3、我们再次请…

【C++】多线程的学习笔记(3)——白话文版(bushi

前言 好久没有继续写博客了&#xff0c;原因就是去沉淀了一下偷懒了一下 现在在学网络编程&#xff0c;c的多线程也还在学 这一变博客就讲讲c中的Condition Variable库吧 Condition Variable的简介 官方原文解释 翻译就是 条件变量是一个对象&#xff0c;它能够阻止调用…

腾讯云服务器秒杀什么时候开始?腾讯云服务器秒杀时间

腾讯云服务器秒杀什么时候开始呢&#xff1f;我们一起来揭晓答案&#xff01; 腾讯云服务器秒杀活动即日起至2023-11-30 23:59:59&#xff0c;每日0点限量秒杀。这意味着&#xff0c;每一天的开始&#xff0c;你都有机会抢到心仪的服务器。秒杀活动入口&#xff1a;https://te…

面试题-3

1.说一下原型链 原型就是一个普通对象,它是为构造函数实例共享属性和方法&#xff0c;所有实例中引用原型都是同一个对象 使用prototype可以把方法挂载在原型上&#xff0c;内存值保存一致 _proto_可以理解为指针,实例对象中的属性,指向了构造函数的原型(prototype) 2.new操…

image图片之间的间隙消除

多个图片排列展示&#xff0c;水平和垂直方向的间隔如何消除 垂直方向 vertical-align 原因&#xff1a; vertical-align属性主要用于改变行内元素的对齐方式&#xff0c;行内元素默认垂直对齐方式是基线对齐&#xff08;baseline&#xff09; 这是因为图片属于行内元素&…

双极性集成电路芯片 D7312,可用于小型收录机中作前置放大电路。电源开关冲击噪音小、 反应快

一块双极性集成电路芯片 D7312。可用于小型收录机中作前置放大电路。 主要特点&#xff1a; ● 含ALC电路和ALC检波电路。 ● 外接元件少。 ● 增益高&#xff0c;噪声低。 ● 静态电流小 ● 电源开关冲击噪音小、 反应快 ● 具有过热保护功能 …

爬取全国高校数据 (高校名称,高校所在地,高校类型,高校性质,高校特色,高校隶属,学校网站)

爬取全国高校数据 网站&#xff1a; 运行下面代码得到网站. import base64 # 解码 website base64.b64decode(IGh0dHA6Ly9jb2xsZWdlLmdhb2thby5jb20vc2NobGlzdC8.encode(utf-8)) print(website)分析&#xff1a; 我们需要爬取的字段&#xff0c;高校名称&#xff0c;高校所…

Win10专业版如何重装-Win10专业版重装系统教程

Win10专业版如何重装&#xff1f;Win10专业版系统能够用户带来丰富的功能服务&#xff0c;用户操作需求轻松得到满足。如果我们在Win10专业版电脑中&#xff0c;遇到了系统问题&#xff0c;这时候可以考虑重新安装Win10专业版系统&#xff0c;从而解决系统出现的问题。下面小编…