哈希表巧解字母异位词分组:从思路到实现的全方位讲解

在本题中,我们需要将一组字符串按照字母异位词进行分组。字母异位词是由相同字母组成的单词,只是字母排列顺序不同。例如 “eat” 和 “tea” 是字母异位词,因为它们的字母组成完全相同。

题目链接:49. 字母异位词分组 - 力扣(LeetCode)


解题思路

为了分组字母异位词,我们需要找到一种方法,能够识别出字母异位词之间的共同特征。对同一个字母异位词组中的所有单词,我们可以通过以下方法找到它们的特征。

方法 1:字符串排序法

字母异位词的一个明显特征是,它们都包含相同的字母,且每个字母的出现次数相同。因此,如果我们将每个单词的字母排序,那么字母异位词的排序结果是一样的。

比如对于单词列表 ["eat", "tea", "tan", "ate", "nat", "bat"],我们可以将每个单词按字母顺序排序:

  • eat 排序后变为 aet
  • tea 排序后变为 aet
  • tan 排序后变为 ant
  • ate 排序后变为 aet
  • nat 排序后变为 ant
  • bat 排序后变为 abt

我们发现 "eat""tea""ate" 排序后都是 "aet",所以它们是字母异位词,可以分为一组。同样 "tan""nat" 排序后都是 "ant",可以分为另一组。

实现步骤
  1. 使用一个 unordered_map,其中键为排序后的字符串,值为一个 vector,用来存储属于该组的字母异位词。
  2. 遍历每个字符串,将其排序,然后将排序后的字符串作为键,原始字符串作为值,添加到 unordered_map 中对应的组。
  3. 最后,将 unordered_map 中的所有值(即字母异位词组)提取出来,组成最终的结果列表。
代码实现
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <algorithm>class Solution {
public:std::vector<std::vector<std::string>> groupAnagrams(std::vector<std::string>& strs) {std::unordered_map<std::string, std::vector<std::string>> anagramMap;// 遍历每个字符串for (const std::string& str : strs) {std::string sorted_str = str;  // 复制字符串std::sort(sorted_str.begin(), sorted_str.end());  // 排序字符串anagramMap[sorted_str].push_back(str);  // 将原字符串放入排序后键的组中}// 将map中所有的值转换为结果格式std::vector<std::vector<std::string>> result;for (const auto& pair : anagramMap) {result.push_back(pair.second);}return result;}
};
示例与解释

我们来看一个示例输入 strs = ["eat", "tea", "tan", "ate", "nat", "bat"]

  1. 首先,遍历每个字符串并排序:

    • eat 排序为 aettea 排序为 aetate 排序为 aet
    • tan 排序为 antnat 排序为 ant
    • bat 排序为 abt
  2. 按照排序后的字符串作为键,将字母异位词添加到 unordered_map

    • aet 对应的值为 ["eat", "tea", "ate"]
    • ant 对应的值为 ["tan", "nat"]
    • abt 对应的值为 ["bat"]
  3. unordered_map 中的所有值(即每个字母异位词组)提取出来,组成结果:

    • 结果为 [["eat", "tea", "ate"], ["tan", "nat"], ["bat"]]
时间和空间复杂度分析
  • 时间复杂度O(N * K log K),其中 N 是字符串的数量,K 是字符串的平均长度。排序每个字符串的复杂度是 O(K log K)
  • 空间复杂度O(N * K),用于存储所有字符串的分组。

方法 2:字符频次法

如果字符串较长,排序的效率会变低。我们可以采用另一种方法,用字符频次来表示每个字符串。

对于每个字符串,统计它包含的每个字母的次数,然后将字母频次数组作为该字符串的特征。例如:

  • eat 的频次数组是 [1, 1, 0, 0, ..., 1],表示有 1 个 ‘a’、1 个 ‘e’、1 个 ‘t’。
  • teaate 的频次数组相同,因此它们是字母异位词。
实现步骤
  1. 对于每个字符串,计算它的字符频次数组,将频次数组转换为字符串作为键。
  2. 使用 unordered_map 将该键与字母异位词组对应起来。
  3. 最后,将字母异位词组提取出来,组成结果列表。
代码实现
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>class Solution {
public:std::vector<std::vector<std::string>> groupAnagrams(std::vector<std::string>& strs) {std::unordered_map<std::string, std::vector<std::string>> anagramMap;for (const std::string& str : strs) {std::vector<int> count(26, 0);  // 初始化26个字母的频次for (char c : str) {count[c - 'a']++;}std::string key;for (int freq : count) {key += "#" + std::to_string(freq);  // 将频次数组转换成键}anagramMap[key].push_back(str);  // 将原字符串添加到对应的组中}std::vector<std::vector<std::string>> result;for (const auto& pair : anagramMap) {result.push_back(pair.second);}return result;}
};
示例与解释

对于输入 ["eat", "tea", "tan", "ate", "nat", "bat"]

  1. 首先,将每个字符串转换为频次数组:

    • eat 的频次数组为 [1, 0, 0, ..., 1]teaate 也相同。
    • tannat 的频次数组相同,为 [1, 0, 0, ..., 1]
    • bat 的频次数组为 [1, 1, 0, ..., 1]
  2. 使用频次数组字符串作为键,构建 unordered_map

    • 相同频次数组的字符串会分到同一个组中。
  3. 提取 unordered_map 的值,得到最终结果。


总结

在这道题中,我们介绍了两种主要的解决方案:

  1. 字符串排序法:通过对每个字符串排序,使字母异位词具有相同的排序结果,从而可以分组。这种方法简单直接,适合普通情况。
  2. 字符频次法:通过统计字符出现频率,将频率数组作为特征,用于分组。该方法避免了排序,适合字符串较长的情况。

这两种方法可以根据实际情况选择使用。理解这两种方法的不同特征,可以帮助我们更好地解决字母异位词分组的问题。

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

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

相关文章

【C++练习】使用C++编写程序计算π的近似值

题目&#xff1a;使用C编写程序计算π的近似值 描述&#xff1a; 编写一个C程序&#xff0c;使用一个特定的数学公式来计算圆周率&#xff08;π&#xff09;的近似值。该程序定义了一个函数calculatePi()&#xff0c;该函数通过一个迭代算法和一个涉及反正切函数&#xff08;…

Hook小程序

下载&#xff1a; https://github.com/JaveleyQAQ/WeChatOpenDevTools-Python 配置&#xff1a; pip install -r requirements 实现&#xff1a; 开启小程序开发者模式&#xff0c;类似浏览器F12 效果&#xff1a; 使用&#xff1a; 退出微信&#xff0c;进入安装的目录…

如何在pycharm中 判断是否成功安装pytorch环境

1、在电脑开始端&#xff0c;找到 2、打开后 在base环境下 输入conda env list 目前我的环境中没有pytorch 学习视频&#xff1a;【Anaconda、Pytorch、Pycharm到底是什么关系?什么是环境?什么是包?】https://www.bilibili.com/video/BV1CN411s7Ue?vd_sourcefad0750b8c6…

AI陪伴走热,网易云信“融合通讯+AI”新方案发布!附场景App及源码

信息秒回、不会失联、724h 情感陪伴、随时提供情绪价值......在 AI 能力越来越强大的今天&#xff0c;我们开始有了“AI 助手”、“AI 搭子”&#xff0c;甚至开始谈起“AI 男友/女友”&#xff0c;AI 的角色早已超越了简单的生产力工具&#xff0c;它正深入到我们生活的方方面…

力扣 LeetCode 704. 二分查找(Day1:数组)

解题思路&#xff1a; 二分查找主要分为[ left , right ]左闭右闭和[ left , right )左闭右开两种 此处采取[ left , right ]左闭右闭写法 注意&#xff1a; 1. right的初始化取值 2. while中取等 3. right mid -1 ; class Solution {public int search(int[] nums, i…

java-AOP编程示例

SpringBoot工程&#xff0c;有不懂的留言or Kimi一下 LogAspect.java package com.xxx.javaaopdemo.Aspect;import com.xxx.javaaopdemo.LogAnnotation; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang…

Kafka入门:Java客户端库的使用

在现代的分布式系统中&#xff0c;消息队列扮演着至关重要的角色&#xff0c;而Apache Kafka以其高吞吐量、可扩展性和容错性而广受欢迎。本文将带你了解如何使用Kafka的Java客户端库来实现生产者&#xff08;Producer&#xff09;和消费者&#xff08;Consumer&#xff09;的基…

使用 npm 安装 Yarn

PS E:\WeChat Files\wxid_fipwhzebc1yh22\FileStorage\File\2024-11\spid-admin\spid-admin> yarn install yarn : 无法将“yarn”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写&#xff0c;如果包括路径&#xff0c;请确保路径正确&#xff0c;然后…

力扣617:合并二叉树

给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵新二叉树。合并的规则是&#xff1a;如果两个节点重叠&#…

谷歌浏览器支持的开发者工具详解

谷歌浏览器&#xff08;Google Chrome&#xff09;是全球最受欢迎的网页浏览器之一&#xff0c;它不仅提供了快速、安全的浏览体验&#xff0c;还为开发者提供了强大的开发者工具。本文将详细介绍如何使用谷歌浏览器的开发者工具&#xff0c;并解答一些常见问题。&#xff08;本…

HTB:OpenAdmin[WriteUP]

目录 连接至HTB服务器并启动靶机 使用nmap对靶机TCP端口进行开放扫描 继续使用nmap对靶机22、80端口进行脚本、服务扫描 使用Dirbuster对靶机网页路径进行递归扫描 ​编辑 尝试在searchsploit中搜索改WebAPP漏洞 横向移动(其实没有横) 启动Metasploit 特权提升 USER_…

IO作业5

设置双信号实现交替生产者线程和消费者线程 #include <myhead.h> int n0; pthread_mutex_t fastmutex;//定义互斥锁 pthread_cond_t cond;//定义条件变量 pthread_cond_t cond2; void *product() {int i;for(i0;i<10;i){n;printf("我生产了一台特斯拉n%d\n"…

Web3.0安全开发实践|BNB链安全开发,这10大实用tips一定要收藏

BNB Chain是Web3世界中最受欢迎的区块链之一&#xff0c;其费用合理、交易迅速以及项目生态系统丰富几大原因吸引了广大用户。与任何的区块链都一样&#xff0c;BNB Chain上的开发者在开发过程中首先考虑的应该是安全问题&#xff1a;因为任何资金的损失都会导致用户对协议及平…

QT开发笔记之小知识

QCoreApplication::aboutToQuit 主事件循环退出前发出的信号&#xff0c;是程序退出前等待QT线程退出回收资源的神器。 官方帮助文档 [signal] void QCoreApplication::aboutToQuit() 该信号在应用程序即将退出主事件循环时发出&#xff0c;例如&#xff1a;当事件循环级别降至…

插入排序(C语言)

直接插入排序的基本思想&#xff1a;把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有的记录插入完为止&#xff0c;得到一个新的有序序列 。 一、步骤 1.给定一个乱序的数组&#xff0c;如 从第一个元素开始排序&#xff0c;当只…

文心一言 VS 讯飞星火 VS chatgpt (389)-- 算法导论25.1 2题

二、为什么要求对于所有的 1 ⩽ i ⩽ n 1⩽i⩽n 1⩽i⩽n&#xff0c;有 w i i 0 w_{ii}0 wii​0 &#xff1f;如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 在许多数学和计算应用中&#xff0c;要求矩阵 W W W 的对角线元素 w i i 0 w_{ii} 0 wii​0 是…

Java多线程详解⑦(全程干货!!!)内存可见性 || volatile || JMM || wait notify notifyAll

这里是Themberfue 在上一节中&#xff0c;我们讨论了死锁的概念&#xff0c;产生的场景 &#xff0c;产生的必要条件...... 内存可见性 我们先来看一段百度百科关于 "内存可见性" 的解释 "内存可见性" 就是造成线程安全问题的原因之一 如果是单纯地看…

安装双系统(linux操作系统(debian)安装)

参考博客&#xff1a;戴尔服务器安装Debian11过程_戴尔t130安装debian-CSDN博客 一.腾出一个50G以上的空间&#xff0c;准备装操作系统 1.底部搜索计算机管理&#xff0c;选择磁盘管理 本人已预留400GB磁盘空间安装ubuntu系统&#xff0c;若没有预留空间&#xff0c;则可以选…

心系天下三星W25:记录盛世影像 见证华彩时光

悠然岁月中&#xff0c;被定格的瞬间总是历久弥新。心系天下三星W25以传世经典之姿跃然于掌中&#xff0c;将精致外形与精湛工艺合二为一&#xff0c;彰显出持有者的高雅气质。同时&#xff0c;强悍的影像系统则使之成为光影艺术的记录者&#xff0c;无论是捕捉人生风华&#x…

修改msyql用户密码及更新mysql密码策略

查看mysql中初始的密码策略 SHOW VARIABLES LIKE validate_password% 2. 修改默认密码策略 -- 0 或者 LOW 只验证长度-- 1 或者 MEDIUM 验证长度、数字、大小写、特殊字符-- 2 或者 STRONG 验证长度、数字、大小写、特殊字符、字典文件set global validate_password.policy0;…