当前位置: 首页 > article >正文

【哈希表与字符串的算法之路:思路与实现】—— LeetCode

文章目录

  • 两数之和
  • 面试题01.02.判定是否为字符重排
  • 存在重复元素
  • 存在重复元素||
  • 字母异位词分组
  • 最长公共前缀和
  • 最长回文子串
  • 二进制求和
  • 字符串相乘

两数之和

在这里插入图片描述
这题的思路很简单,在读完题目之后,便可以想到暴力枚举,直接遍历整个数组两遍即可,但是时间复杂度高,下面是运行之后的结果
在这里插入图片描述

很简单快速的将这个题目写完了,但是有没有更高效,时间复杂度更低的方法呢?
当然!
思路:

  • 利用哈希表进行优化已经知道了target,那么遍历让x = target-nums[i]如果x在哈希表中存在,那么就存在这组元素——即结果。
class Solution 
{
public:vector<int> twoSum(vector<int>& nums, int target) {unordered_map<int, int> hash;for(int i = 0; i < nums.size(); i++){int x = target - nums[i];if(hash.count(x)) return {hash[x], i};hash[nums[i]] = i;}return {};}
};

面试题01.02.判定是否为字符重排

在这里插入图片描述
这个题目也是一个很经典的题目,也是一个一眼题

  • 方法一:直接将两个字符串进行排序,相同就是true,不同就是false。时间复杂度也是最优的
class Solution 
{
public:bool CheckPermutation(string s1, string s2){sort(s1.begin(),s1.end());sort(s2.begin(),s2.end());if(s1 == s2) return true;else return false;}
};
  • 方法二:可以用一个数组替代哈希表,将遍历一组字符串进入哈希表,然后再遍历另外一组字符串——从哈希表中依次减少另外一组字符串的个数,最后结果为0便是true,否则剩余数字就是false。
class Solution 
{
public:bool CheckPermutation(string s1, string s2) {if(s1.size() != s2.size()) return false;int hash[26] = { 0 };//先统计第一个字符串的信息for(auto ch : s1)hash[ch - 'a']++;//扫描第二个字符串,看看能不能重排for(auto ch : s2){hash[ch - 'a']--;if(hash[ch - 'a'] < 0) return false;}        return true;}
};

存在重复元素

在这里插入图片描述

  • 思路:
    将数组一遍遍历,一边插入到哈希表当中,如果遍历到每个元素的时候已经存在该元素,直接返回true即可,如果遍历完之后没有元素了返回false。
class Solution 
{
public:bool containsDuplicate(vector<int>& nums) {// 创建一个无序集合,用于存储nums向量中的唯一元素unordered_set <int> hash;// 遍历nums向量中的每个元素for(auto x : nums){// 如果元素已经在集合中,说明存在重复元素if(hash.count(x)) return true;  // 如果发现重复元素,返回trueelse hash.insert(x);  // 如果没有重复元素,将该元素插入集合中}// 如果遍历完后没有发现任何重复元素,返回falsereturn false;}
};

存在重复元素||

在这里插入图片描述

  • 思路: 这题跟上面一题基本一样只不过增加了一个| i - j | <= k的条件。
class Solution 
{
public:bool containsNearbyDuplicate(vector<int>& nums, int k) {// 创建一个哈希表,用于存储每个元素及其最后出现的位置unordered_map<int, int> hash;// 遍历nums向量中的每个元素for(int i = 0; i < nums.size(); i++){// 如果当前元素在哈希表中已经存在if(hash.count(nums[i])){// 判断当前索引与该元素上次出现索引的差是否小于等于kif(i - hash[nums[i]] <= k) return true;  // 如果差值小于等于k,返回true,表示找到满足条件的重复元素}// 更新当前元素在哈希表中的位置hash[nums[i]] = i;}// 如果遍历完所有元素都没有找到满足条件的重复元素,返回falsereturn false;}
};

字母异位词分组

在这里插入图片描述

  • 思路:
  1. 排序法:
    对于每个字符串,将其按字母排序。排序后的字符串可以作为它们的“标识符”,即所有字母异位词排序后得到的字符串是相同的。
    例如,“eat”和“tea”排序后都会变成“aet”,这使得我们能够将它们归为一组。

  2. 使用哈希表分组:
    使用一个哈希表 unordered_map<string, vector>,其中键是排序后的字符串,值是具有相同排序后的字母异位词的字符串集合。
    对于每个字符串,排序并将它放入对应的组中。如果该组已经存在,就将其添加到对应组里;如果该组不存在,就创建新组。

  3. 提取结果:
    最后,从哈希表中提取出所有的字母异位词组并返回。

class Solution 
{
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {// 创建一个哈希表,key是排序后的字符串,value是与该排序字符串对应的字母异位词列表unordered_map <string, vector<string>> hash;// 1. 将所有字符串排序并分组for(auto& s : strs){// 将字符串复制到tmp中,然后排序string tmp = s;sort(tmp.begin(), tmp.end());// 根据排序后的字符串,将原始字符串加入哈希表的对应组中hash[tmp].push_back(s);}// 2. 从哈希表中提取出结果vector<vector<string>> ret;for(auto&[x, y] : hash){// 将每一组字母异位词加入到结果列表中ret.push_back(y);}// 返回结果return ret;}
};

最长公共前缀和

在这里插入图片描述

  • 思路:
    这道题的思路是通过逐个字符地检查所有字符串的字符来找出最长公共前缀。从第一个字符串的第一个字符开始,逐个比较该位置上其他字符串的字符是否相同。如果遇到不同的字符或某个字符串的长度不足,就返回当前找到的公共前缀。如果没有遇到不匹配的字符,说明第一个字符串本身就是所有字符串的公共前缀,直接返回它——中心扩展算法
class Solution 
{
public:string longestCommonPrefix(vector<string>& strs) {// 遍历第一个字符串的每一个字符for(int i = 0; i < strs[0].size(); i++){// 获取当前字符char tmp = strs[0][i];// 遍历后续的字符串,检查是否在当前字符位置上与第一个字符串相同for(int j = 1; j < strs.size(); j++){// 如果某个字符串的长度小于等于i,或者字符不匹配,返回从0到i的子串作为公共前缀if(i == strs[j].size() || tmp != strs[j][i])return strs[0].substr(0, i);}}// 如果没有遇到不匹配的情况,说明第一个字符串就是公共前缀return strs[0];}
};

最长回文子串

  • 思路:
    这道题要求找到一个字符串中最长的回文子串。回文串是指从前往后和从后往前读都相同的字符串。我们可以通过 中心扩展法 来解决这个问题。每个回文子串都有一个中心,中心可以是一个字符(对于奇数长度回文串)或者两个字符之间(对于偶数长度回文串)。从每个字符(或字符间隙)向外扩展,检查左右两边的字符是否相等,直到不再相等为止。
class Solution 
{
public:string longestPalindrome(string s) {// 获取字符串长度nint n = s.size(), begin = 0, len = 0;// 遍历每个字符,尝试找到以该字符为中心的回文串for(int i = 0; i < n; i++){// 处理奇数长度回文串,以字符s[i]为中心int right = i, left = i;// 扩展左右两边,直到不满足回文条件while(left >= 0 && right < n && s[left] == s[right]){left--;right++;}// 更新最长回文串的起始位置和长度if(right - left - 1 > len){begin = left + 1;len = right - left - 1;}// 处理偶数长度回文串,以字符s[i]和s[i+1]为中心right = i + 1, left = i;while(left >= 0 && right < n && s[left] == s[right]){left--;right++;}// 更新最长回文串的起始位置和长度if(right - left - 1 > len){begin = left + 1;len = right - left - 1;}}// 返回最长回文子串return s.substr(begin, len);}
};

二进制求和

在这里插入图片描述

  • 思路:
    我们从 a 和 b 的末尾(即最低位)开始逐位进行加法运算,类似于手动加法的过程。每一位相加时,判断是否需要进位。进位的处理通过变量 t 来存储,当两位数字加起来大于或等于2时,t 就会向下一位传递进位。最终,逐位的结果被累积到字符串 ret 中,并且需要反转,因为我们从低位到高位计算。整个过程确保处理了两者的不同长度以及最终的进位。
class Solution 
{
public:string addBinary(string a, string b) {string ret; // 用于存储结果的字符串int cur1 = a.size() - 1, cur2 = b.size() - 1, t = 0; // cur1, cur2分别是a和b的当前字符索引,t是进位// 遍历两个字符串直到都遍历完并且没有进位while(cur1 >= 0 || cur2 >= 0 || t){// 如果a还有剩余位,取出a对应位置的数字并加到t中if(cur1 >= 0) t += a[cur1--] - '0';  // 如果b还有剩余位,取出b对应位置的数字并加到t中if(cur2 >= 0) t += b[cur2--] - '0';  // 将当前位的结果加到结果字符串中,t % 2是当前位(0或1),进位需要除以2ret += t % 2 + '0';t /= 2; // 更新进位,t // 2}// 由于我们是从低位到高位处理的,最后需要反转结果字符串reverse(ret.begin(), ret.end());return ret; // 返回加法结果的二进制字符串}
};

字符串相乘

在这里插入图片描述

  • 思路:
    这道题目要求实现两个大整数的乘法。我们不能直接将两个大整数转换为整数进行计算,因为它们的长度可能超出整数类型的表示范围。我们通过模拟竖式乘法的方法来手动计算乘积。首先,我们逆序遍历两个字符串,将每一位的数字相乘并加到临时结果数组中,处理乘法的每一位。然后,我们处理进位,最后将结果反转并处理前导零,得到最终的乘积结果。
    在这里插入图片描述
    在这里插入图片描述
class Solution 
{
public:string multiply(string num1, string num2){// 获取两个字符串的长度int m = num1.size(), n = num2.size();// 反转字符串,以便从低位开始计算reverse(num1.begin(), num1.end());reverse(num2.begin(), num2.end());// 临时数组用于存储每一位的乘积结果vector<int> tmp(m + n - 1);// 进行无进位的相乘for(int i = 0; i < m; i++)for(int j = 0; j < n; j++)tmp[i + j] += (num1[i] - '0') * (num2[j] - '0');// 处理进位int cur = 0, t = 0;string ret;while(cur < m + n - 1 || t != 0){// 将当前的乘积加到结果中if(cur < m + n - 1) t += tmp[cur++];// 取当前位的数字,并更新进位ret += t % 10 + '0';t /= 10;}// 处理前导零while(ret.size() > 1 && ret.back() == '0') ret.pop_back();// 反转最终的结果字符串reverse(ret.begin(), ret.end());return ret;  // 返回最终的乘积结果}
};

相关文章:

【哈希表与字符串的算法之路:思路与实现】—— LeetCode

文章目录 两数之和面试题01.02.判定是否为字符重排存在重复元素存在重复元素||字母异位词分组最长公共前缀和最长回文子串二进制求和字符串相乘 两数之和 这题的思路很简单&#xff0c;在读完题目之后&#xff0c;便可以想到暴力枚举&#xff0c;直接遍历整个数组两遍即可&…...

基于Android的记事本APP设计与实现:从需求分析到功能实现(超级简单记事本,附源码+文档报告)

基于Android的记事本APP设计与实现&#xff1a;从需求分析到功能实现 &#xff08;以前大学课堂作业&#xff0c;抄在这里当个回忆吧&#xff09; 引言 随着社会的不断进步&#xff0c;信息化建设不断发展&#xff0c;电子文字输入在生活、学习、工作中占有越来越重要的作用…...

eNSP中路由器的CON/AUX接口、GE Combo接口、Mini USB接口、USB接口、WAN侧uplink接口、FE接口、GE接口介绍

路由器常见接口的详细介绍及其应用示例&#xff1a; 1. CON/AUX 接口 全称&#xff1a;Console/Auxiliary&#xff08;控制台/辅助接口&#xff09;作用&#xff1a; CON&#xff08;Console&#xff09;&#xff1a;通过命令行界面&#xff08;CLI&#xff09;直接配置路由器…...

Hello Mr. My Yesterday日文歌词附假名注音,祭奠逝去的青春

hello mr. my yesterday Hundred Percent Free Hello Mr. my yesterday云っておくれよ “夢叶うその瞬間にまた逢える”と 前方の幾多前途多難の未知 後方の道後悔も知った 経験と価値 夢なかば 一本の道結果だが ひとつだけ知りたいよ 神様がいるのなら “幸せの定義っ…...

ubuntu ollama+dify实践

安装ollama 官网的指令太慢了&#xff0c;使用以下指令加速&#xff1a; export OLLAMA_MIRROR"https://ghproxy.cn/https://github.com/ollama/ollama/releases/latest/download" curl -fsSL https://ollama.com/install.sh | sed "s|https://ollama.com/dow…...

S7-1200 G2移植旧版本S7-1200程序的具体方法示例

S7-1200 G2移植旧版本S7-1200程序的具体方法示例 前期概要: S7-1200 G2必须基于TIA博途V20,之前的程序可通过移植的方式在新硬件上使用。 该移植工具可自动将TIA Portal 项目从 S7-1200 移植到更新的S7-1200 G2。 注意: 该插件支持在同一TIA Portal项目实例内将软件和/或硬…...

新办公室哪款空气净化器除甲醛效果好?高效除甲醛,提升效率

现代办公环境中&#xff0c;空气质量对员工的健康与工作效率产生着不可忽视的影响。尤其是新装修的办公室&#xff0c;往往因为空气中的甲醛浓度超标而导致一系列健康问题。因此&#xff0c;选择一款性能优越的除甲醛空气净化器就显得尤为重要。合适的空气净化器不仅可以有效过…...

塑造企业数字化形象:企业信息化UI界面设计的关键要素

引言 在数字化转型的大潮中&#xff0c;企业信息化系统的UI&#xff08;用户界面&#xff09;界面设计不仅是技术实现的最后一环&#xff0c;更是塑造企业数字化形象、提升用户体验、增强业务效率的重要手段。优秀的UI设计能够直观展现企业价值观&#xff0c;提升用户粘性&…...

大视频背景暗黑风格的wordpress企业主题免费下载

整体风格是黑色的&#xff0c;首页首屏大视频背景&#xff0c;动态效果非常好。向下滚动时&#xff0c;滚动的特效也不错。 原文 https://www.bixugao.com/wp/26.html...

CUDA编程之内存零拷贝技术

一、实现原理 零拷贝内存通过将‌主机锁页内存‌直接映射到设备地址空间&#xff0c;实现CPU与GPU共享内存&#xff0c;避免显式数据拷贝‌。锁页内存通过cudaHostAlloc或cudaHostRegister分配&#xff0c;确保物理地址固定且不被操作系统换页&#xff0c;从而支持DMA&#xff…...

C语言基础知识04

指针 指针概念 指针保存地址&#xff0c;地址是字节的编号 指针类型和保存的地址类型要一直 使用时注意&#xff0c;把地址转换为&变量的格式来看 int a[3]; a转为&a[0] 指针的大小 64bit 固定8字节&#xff0c; 32bit 固定4字节 指针…...

在 Java 中,== 和 equals 的区别

1. 运算符 作用&#xff1a;比较两个对象的 内存地址&#xff08;引用类型&#xff09;或 值&#xff08;基本数据类型&#xff09;。 适用场景&#xff1a; 基本数据类型&#xff08;int, char, boolean 等&#xff09;&#xff1a;直接比较值是否相等。 引用类型&#xff…...

Qt开发:QtWebEngine中操作选择文本

查找选择 在QtWebEngine中&#xff0c;可以使用QWebEnginePage的findText方法来查找文本&#xff0c;查找成功以后&#xff0c;将自动选择当前文本。 QWebEnginePage可以通过QWebEngineView的page()来取得。 比如&#xff0c;如下代码可以在页面中查找hello,world并选择。 …...

VUE的脚手架搭建引入类库

VUE的小白脚手架搭建 真的好久好久自己没有发布自己博客了,对于一直在做后端开发的我 ,由于社会卷啊卷只好学习下怎么搭建前端,一起学习成长吧~哈哈哈(最终目的,能够懂并简易开发) 文章目录 VUE的小白脚手架搭建1.下载node.js2.安装vue脚手架3.创建一个项目4.代码规范约束配置(…...

分布式系统日志排查综合场景

排查背景 在一个大型分布式电商系统中&#xff0c;用户反馈在进行商品结算时出现了报错。系统由多个子系统构成&#xff0c;包括商品管理系统、订单系统、支付系统等&#xff0c;各子系统分布在不同服务器上&#xff0c;且日志文件分散存储。 排查过程 确定当前位置并切换到可…...

android lmkd.rc 介绍

service service lmkd /system/bin/lmkdclass coreuser lmkdgroup lmkd system readproccapabilities DAC_OVERRIDE KILL IPC_LOCK SYS_NICE SYS_RESOURCEcriticalsocket lmkd seqpacketpasscred 0660 system systemtask_profiles ServiceCapacityLow属于核心服务组&#xff0…...

Android Studio执行Run操作报Couldn‘t terminate previous instance of app错误

步骤1、在项目根目录下build.gradle文件最后添加如下内容 //自定义任务名&#xff1a;assembleAndInstall tasks.register(assembleAndInstall, Exec.class, new Action<Exec>() {Overridevoid execute(Exec exec) {//设置自定义任务组名exec.setGroup(custom task)//当…...

Matlab 双线性插值(二维)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 双线性插值是一种 二维插值方法,用于计算 栅格(Grid) 或 像素点 之间的插值值。它主要用于 图像缩放、旋转、变换 等操作,以在新像素位置估算灰度值或颜色值。 如上图所示,假设存在一个二维离散函数(如图像)…...

1700. 无法吃午餐的学生数量

无法吃午餐的学生数量 题目描述尝试做法推荐做法 题目描述 学校的自助午餐提供圆形和方形的三明治&#xff0c;分别用数字 0 和 1 表示。所有学生站在一个队列里&#xff0c;每个学生要么喜欢圆形的要么喜欢方形的。 餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个…...

uv命令介绍(高性能Python包管理工具,旨在替代pip、pip-tools和virtualenv等传统工具)

文章目录 **主要功能**1. **快速安装和管理 Python 包**2. **生成和管理锁文件 (requirements.lock)**3. **创建虚拟环境**4. **与 poetry 兼容** **核心优势**1. **极快的速度**&#xff1a;基于 Rust 实现&#xff0c;利用多线程和缓存大幅加速依赖解析。2. **轻量且独立**&a…...

杨辉三角形(信息学奥赛一本通-2043)

【题目描述】 例5.11 打印杨辉三角形的前n(2≤n≤20)行。杨辉三角形如下图&#xff1a; 当n5时 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 输出&#xff1a; 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 【输入】 输入行数n。 【输出】 输出如题述三角形。n行&#…...

使用easyexcel实现单元格样式设置和下拉框设置

1.单元格样式设置 1.1实体类 public class DemoData {ExcelProperty("PK")private String name;ExcelProperty("年龄")private int age;// 必须提供无参构造方法public DemoData() {}public DemoData(String name, int age) {this.name name;this.age …...

TCP 三次握手四次挥手过程详解

注&#xff1a;本文为 “TCP 的三次握手与四次挥手” 相关文章合辑。 英文引文&#xff0c;机翻未校。 中文引文&#xff0c;未整理去重。 英文引文第二篇&#xff0c;实为国内《稀土掘金技术社区》文章&#xff0c;没检索到原文&#xff0c;此处 “出口转内销” 。 如有内…...

射频相关概念

射频&#xff08;Radio Frequency, RF) 是电磁波谱中频率范围在 3 kHz 到 300GHz的电磁波&#xff0c;广泛应用于通信、雷达、广播、医疗等领域。其基本原理涉及电磁波的产生、传播、调制与解调&#xff0c;以及射频系统的设计。以下是射频技术的核心要点&#xff1a; 1. 电磁…...

几款可用于绘制工艺原理图的开源框架

一、LogicFlow 由滴滴团队开发的开源流程图框架&#xff0c;支持高度定制的工艺原理图绘制。 • 核心特性&#xff1a; • 提供拖拽式界面和丰富的节点类型&#xff08;矩形、圆形、多边形等&#xff09;&#xff0c;支持自定义节点形状、样式和交互逻辑。 • 支持插件扩展&am…...

27.卷2的答案

CSP-J离我们不远了&#xff0c;加加油啦&#xff01; 1.堆排序最坏时间复杂度是&#xff1f; 解析&#xff1a;平时多多练习可知&#xff0c;最坏时间复杂度是O(n log n)。 2.哪条能将s中的数值保留一位&#xff0c;并将第二位四舍五入&#xff1f; 解析&#xff1a;经过试…...

程序编译生成的文件

目录 .i 文件 .s 文件 .o文件 总结 在 C 编程中&#xff0c;.i、.s和 .o 文件是编译过程中生成的不同阶段的文件&#xff0c;它们代表不同的含义&#xff1a; .i 文件 全称 &#xff1a;预处理后的文件&#xff08;Intermediate File&#xff09;。 含义&#xff1a;.i文件…...

C++类的基础题(4)

练习1&#xff1a;&#xff08;简单&#xff09; 基于如下程序&#xff0c;按要求修改和完善。 #include <iostream> using namespace std; class Student {public: Student(int n,float s):num(n),score(s){} void change(int n,float s) {numn;scores;} void displ…...

浏览器中输入某个地址后发生了什么

首先浏览器会进行DNS解析&#xff0c;将网址中的域名&#xff08;比如&#xff1a;jcm.com&#xff09;解析为IP地址。理解&#xff1a;DNS为电话本&#xff0c;域名为名字&#xff0c;IP地址为电话号码&#xff1b;其次浏览器需要和网站服务器建立连接&#xff0c;也就是通过三…...

MindGYM:一个用于增强视觉-语言模型推理能力的合成数据集框架,通过生成自挑战问题来提升模型的多跳推理能力。

2025-03-13&#xff0c;由中山大学和阿里巴巴集团的研究团队提出了MindGYM框架&#xff0c;通过合成自挑战问题来增强视觉-语言模型&#xff08;VLMs&#xff09;的推理能力。MindGYM框架通过生成多跳推理问题和结构化课程训练&#xff0c;显著提升了模型在推理深度和广度上的表…...