leetcode 面试经典 150 题:同构字符串

链接同构字符串
题序号205
题型字符串
解法哈希表
难度简单
熟练度✅✅✅✅

题目

  • 给定两个字符串 s 和 t ,判断它们是否是同构的。

  • 如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。

  • 每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。

  • 示例 1:
    输入:s = “egg”, t = “add”
    输出:true

  • 示例 2:
    输入:s = “foo”, t = “bar”
    输出:false

  • 示例 3:
    输入:s = “paper”, t = “title”
    输出:true

  • 提示:
    1 <= s.length <= 5 * 104
    t.length == s.length
    s 和 t 由任意有效的 ASCII 字符组成

哈希表

  1. 哈希表:是一种以键值对(key-value)形式存储数据的数据结构,它通过哈希函数将键映射到特定的位置(索引),从而实现高效的查找、插入和删除操作。

  2. 在 C++ 中,常用的哈希表容器是std::unordered_map

  3. 哈希表的特点

    • 高效性:哈希表的查找、插入和删除操作的平均时间复杂度是 O(1)。这是通过哈希函数直接定位到元素所在的位置实现的。
    • 非有序性:哈希表中的元素存储顺序通常和插入顺序不同,具体取决于哈希函数。如果需要有序的键值对,可以使用 std::map。
    • 冲突处理:当两个键经过哈希函数映射到相同的位置时,称为哈希冲突。哈希表通过链地址法(链表)或开放地址法(探测)解决冲突。
  4. c++ 示例:

#include <unordered_map>
#include <iostream>
using namespace std;int main() {// 定义一个哈希表unordered_map<string, int> myMap;// 插入键值对myMap["apple"] = 5;myMap["banana"] = 3;myMap["cherry"] = 8;// 访问值cout << "apple: " << myMap["apple"] << endl; //输出 5// 查找键是否存在if (myMap.count("banana")) {cout << "banana exists, value: " << myMap["banana"] << endl; //存在,输出值为 3}// 删除键值对myMap.erase("cherry");// 遍历哈希表for (const auto& pair : myMap) {cout << pair.first << ": " << pair.second << endl; //输出 apple 和 banana 的键值对}return 0;
}

题解

  1. 核心要点:使用哈希表(HashMap)来存储字符之间的映射关系。遍历字符串s和t的每个字符,建立字符的映射关系。如果s中的字符已经存在于映射中,并且对应的映射不是当前字符t中的字符,则返回false。如果t中的字符已经存在于映射中,并且对应的映射不是当前字符s中的字符,则返回false。否则,建立字符之间的映射关系。
  2. 复杂度:时间复杂度为O(n),其中 n 为字符串的长度。我们只需同时遍历一遍字符串 s 和 t 即可;空间复杂度为O(字符串的字符集)
  3. c++ 实现算法
bool isIsomorphic(string s, string t) {//两个字符串长度不一样,直接返回 falseif (s.length() != t.length()) return false;//使用两个哈希表来检查双向映射,确保一一对应的关系unordered_map<char, char> mapST; // 映射 s -> tunordered_map<char, char> mapTS; // 映射 t -> sfor (int i = 0; i < s.length(); i++) {char sChar = s[i];char tChar = t[i];// 检查 s -> t 的映射是否一致//检查字符 sChar 是否已经在 mapST 中有记录if (mapST.count(sChar)) {//如果 mapST 中记录的 sChar 的映射值不是当前的 tChar,//说明映射冲突,两个字符串无法是同构的,直接返回 falseif (mapST[sChar] != tChar) return false;} else {//如果 sChar 尚未在 mapST 中建立映射,就将当前的 sChar -> tChar 关系存入映射表中。mapST[sChar] = tChar;}// 检查 t -> s 的映射是否一致if (mapTS.count(tChar)) {if (mapTS[tChar] != sChar) return false;} else {mapTS[tChar] = sChar;}}return true;
}
  1. 算法演示:
  • 示例
    输入:s = “egg”, t = “add”

    • 第一轮 (sChar = ‘e’, tChar = ‘a’)
      mapST 为空,sChar = ‘e’ 不在 mapST 中。
      建立映射:mapST[‘e’] = ‘a’。
    • 第二轮 (sChar =‘g’, tChar = ‘d’)
      sChar = ‘g’ 不在 mapST 中。
      建立映射:mapST[‘g’] = ‘d’。
    • 第三轮 (sChar = ‘g’, tChar = ‘d’)
      sChar = ‘g’ 在 mapST 中,且 mapST[‘g’] == ‘d’,符合映射,继续。 返回 true,两个字符串是同构的。
  • 反例 s = “foo”, t = “bar”

    • 第一轮 (sChar = ‘f’, tChar = ‘b’)
      建立映射:mapST[‘f’] = ‘b’。
    • 第二轮 (sChar = ‘o’, tChar = ‘a’)
      建立映射:mapST[‘o’] = ‘a’。
    • 第三轮 (sChar = ‘o’, tChar = ‘r’)
      sChar = ‘o’ 在 mapST 中,但 mapST[‘o’] != ‘r’。 返回 false。
  1. c++ 完整demo:
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;bool isIsomorphic(string s, string t) {//两个字符串长度不一样,直接返回 falseif (s.length() != t.length()) return false;//使用两个哈希表来检查双向映射,确保一一对应的关系unordered_map<char, char> mapST; // 映射 s -> tunordered_map<char, char> mapTS; // 映射 t -> sfor (int i = 0; i < s.length(); i++) {char sChar = s[i];char tChar = t[i];// 检查 s -> t 的映射是否一致//检查字符 sChar 是否已经在 mapST 中有记录if (mapST.count(sChar)) {//如果 mapST 中记录的 sChar 的映射值不是当前的 tChar,//说明映射冲突,两个字符串无法是同构的,直接返回 falseif (mapST[sChar] != tChar) return false;} else {//如果 sChar 尚未在 mapST 中建立映射,就将当前的 sChar -> tChar 关系存入映射表中。mapST[sChar] = tChar;}// 检查 t -> s 的映射是否一致if (mapTS.count(tChar)) {if (mapTS[tChar] != sChar) return false;} else {mapTS[tChar] = sChar;}}return true;
}int main() {string s = "egg";string t = "add";cout << (isIsomorphic(s, t) ? "true" : "false") << endl;s = "foo";t = "bar";cout << (isIsomorphic(s, t) ? "true" : "false") << endl;s = "paper";t = "title";cout << (isIsomorphic(s, t) ? "true" : "false") << endl;return 0;
}

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

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

相关文章

GPU算力平台的应用之任意门:任意穿搭匹配模型的应用教程

大家好&#xff0c;今天给大家介绍一下&#xff1a;GPU算力平台的应用之任意门:任意穿搭匹配模型的应用教程。 文章目录 一、GPU算力平台概述人工智能智能发展为什么需要GPU算力平台 二、注册与登录账号注册流程 三、平台的应用之Anydoor应用启动器选择Anydoor的应用场景Anydoo…

学习虚幻C++开发日志——创建Selection Widget及其应用

教程视频&#xff1a;脚本冒险 - YouTube 前提&#xff1a;此代码运用到Common UI插件&#xff0c;需将其开启&#xff0c;以免后序编写产生未定义结构体的报错信息&#xff01; 用C进行UI绑定 创建继承于CommonUserWidget的类&#xff0c;此处命名为SelectionBase Select…

Kafka中的Topic和Partition有什么关系?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka中的Topic和Partition有什么关系&#xff1f;】面试题。希望对大家有帮助&#xff1b; Kafka中的Topic和Partition有什么关系&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Apache Kafka 中&#…

SpringBoot Maven 项目 pom 中的 plugin 插件用法整理

把 SpringBoot Maven 项目打包成 jar 文件时&#xff0c;我们通常用到 spring-boot-maven-plugin 插件。 前面也介绍过&#xff0c;在 spring-boot-starter-parent POM 和 spring-boot-starter POM 中都有插件的管理&#xff0c;现在我们就撸一把构建元素中插件的用法。 一、…

c和c++中为什么要防止头文件被重复包含!

在编程中&#xff0c;头文件就像一本工具书&#xff0c;它包含了函数、类、宏、全局变量等的定义和声明&#xff0c;供其他代码文件引用。想象一下&#xff0c;如果你在写一篇文章时&#xff0c;反复引用同一本工具书的内容&#xff0c;会发生什么情况呢&#xff1f; 1. 避免重…

django vue3实现大文件分段续传(断点续传)

前端环境准备及目录结构&#xff1a; npm create vue 并取名为big-file-upload-fontend 通过 npm i 安装以下内容"dependencies": {"axios": "^1.7.9","element-plus": "^2.9.1","js-sha256": "^0.11.0&quo…

MCP(Model Context Protocol)模型上下文协议 进阶篇3 - 传输

MCP 目前定义了两种标准的客户端-服务端通信传输机制&#xff1a; stdio&#xff08;标准输入输出通信&#xff09;HTTP with Server-Sent Events (SSE)&#xff08;HTTP 服务端发送事件&#xff09; 客户端应尽可能支持 stdio。此外&#xff0c;客户端和服务端也可以以插件方…

openai swarm agent框架源码详解及应用案例实战

文章目录 简介数据类型Agent类Response类Result类Swarm类run_demo_loop交互式会话 基础应用agent-handsofffunction-callingcontext_variablestriage_agent 高阶应用通用客服机器人(support bot)构建航班服务agent 参考资料 openai 在24年10月份开源了一个教育性质的多agents协…

【顶刊TPAMI 2025】多头编码(MHE)之极限分类 Part 2:基础知识

目录 1 预热1.1 记号1.2 分类器计算过载问题 2 多头编码&#xff08;MHE&#xff09;2.1 标签分解2.2 多头组合&#xff08;Multi-Head Combination&#xff09; 论文&#xff1a;Multi-Head Encoding for Extreme Label Classification 作者&#xff1a;Daojun Liang, Haixia …

攻防世界 - Misc - Level 1 | 适合作为桌面

关注这个靶场的其它相关笔记&#xff1a;攻防世界&#xff08;XCTF&#xff09; —— 靶场笔记合集-CSDN博客 0x01&#xff1a;考点速览 想要通过本关&#xff0c;你需要掌握以下知识点&#xff1a; Stegolve 查看图片隐写内容。 了解 pyc 文件&#xff0c;并知道如何通过 Wi…

Unity 从零开始的框架搭建1-3 关于命令模式的一些思考

Unity 从零开始的框架搭建1-2 事件的发布-订阅-取消的小优化及调用对象方法总结[半干货]-CSDN博客 本人水平有限 如有不足还请斧正&#xff0c;该文章专栏是向QFrameWork作者凉鞋老师学习总结得来&#xff0c;吃水不忘打井人&#xff0c;不胜感激 关于此模式我曾实现过&#…

UVM :uvm_sequence_item property and methods

transaction是uvm_sequence_item的一个子类。 topic transaction介绍 uvm_sequence_item override Set_type_override:同类型替换 Set_inst_override:同例化替换

SpringBoot原理分析-1

SpringBoot原理分析 作为一个javaer&#xff0c;和boot打交道是很常见的吧。熟悉boot的人都会知道&#xff0c;启动一个springboot应用&#xff0c;就是用鼠标点一下启动main方法&#xff0c;然后等着就行了。我们来看看这个main里面。 SpringBootApplication public class E…

前端(API)学习笔记(CLASS 4):进阶

1、日期对象 日期对象&#xff1a;用来表示事件的对象 作用&#xff1a;可以得到当前系统时间 1、实例化 在代码中发现了new关键字&#xff0c;一般将这个操作称为实例化 创建一个时间对象并获取时间 获得当前时间 const datenew Date() 使用日志查看&#xff0c;得到的…

力扣刷题:二叉树OJ篇(上)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 目录 1.单值二叉树&#xff08;1&#xff09;题目描…

4.1.2 栈和队列(二)

文章目录 队列的定义队列的基本运算队列的存储结构 队列的定义 队列先进先出&#xff0c;仅允许一端插入、一端删除 队尾(Rear)&#xff0c;插入 队头(Front)&#xff0c;删除 队列的基本运算 队列的基本运算 初始化空队列&#xff1a;initQueue(Q)判队空&#xff1a;isEmpty…

【HeadFirst系列之HeadFirst设计模式】第1天之HeadFirst设计模式开胃菜

HeadFirst设计模式开胃菜 前言 从今日起&#xff0c;陆续分享《HeadFirst设计模式》的读书笔记&#xff0c;希望能够帮助大家更好的理解设计模式&#xff0c;提高自己的编程能力。 今天要分享的是【HeadFirst设计模式开胃菜】&#xff0c;主要介绍了设计模式的基本概念、设计模…

Oracle数据库如何找到 Top Hard Parsing SQL 语句?

有一个数据库应用程序存在过多的解析问题&#xff0c;因此需要找到产生大量硬解析的主要语句。 什么是硬解析 Oracle数据库中的硬解析&#xff08;Hard Parse&#xff09;是指在执行SQL语句时&#xff0c;数据库需要重新解析该SQL语句&#xff0c;并创建新的执行计划的过程。这…

【GBT32960协议学习系列】GBT 32960协议的背景、目的和适用范围

GBT 32960协议的背景、目的和适用范围 1. GBT 32960协议的背景 GBT 32960是中国国家标准&#xff0c;全称为《电动汽车远程服务与管理系统技术规范》。该标准由中国国家标准化管理委员会发布&#xff0c;旨在规范电动汽车远程服务与管理系统的技术要求&#xff0c;确保电动汽车…

蓝桥杯备赛:C++基础,顺序表和vector(STL)

目录 一.C基础 1.第一个C程序&#xff1a; 2.头文件&#xff1a; 3.cin和cout初识&#xff1a; 4.命名空间&#xff1a; 二.顺序表和vector&#xff08;STL&#xff09; 1.顺序表的基本操作&#xff1a; 2.封装静态顺序表&#xff1a; 3.动态顺序表--vector&#xff1a;…