leetcode 面试经典 150 题:字母异位词分组

链接 字母异位词分组
题序号 49
题型 字符串
解题方法 哈希表
难度 中等
熟练度 ✅✅✅

题目

  • 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

  • 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

  • 示例 1:

    输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]

    输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

  • 示例 2:

    输入: strs = [""]

    输出: [[""]]

  • 示例 3:

    输入: strs = ["a"]

    输出: [["a"]]

  • 提示:

    1 <= strs.length <= 10^4

    0 <= strs[i].length <= 100

    strs[i] 仅包含小写字母

题解

  1. 核心思想
    • 定义哈希表:使用 unordered_map 来存储每个字母异位词组。键是排序后的字符串,值是一个包含所有字母异位词的 vector。
    • 遍历字符串数组
      对于每个字符串,首先将其复制到一个临时字符串 key 中。
      对 key 进行排序,这样所有字母异位词的排序结果将相同,从而可以用作哈希表的键。
    • 插入哈希表
      将原始字符串插入到哈希表中,键为排序后的 key。这样,所有字母异位词都会被插入到同一个键对应的值(即 vector)中。
  2. 复杂度:时间复杂度O( n * k ),其中 n 是字符串数组的长度,k 是字符串的最大长度。每个字符串的字符计数需要 O(k) 的时间。空间复杂度:O( n * k ),主要是哈希表存储的空间。
  3. c++ 实现算法
cpp 复制代码
vector<vector<string>> groupAnagrams(vector<string>& strs) {
    
    unordered_map<string, vector<string>> hashTable; // 定义哈希表

    //遍历输入的字符串数组
    for (const string& str : strs) {

        string key = str; //将当前字符串赋值给 key
        
        sort(key.begin(), key.end()); // 将字符串排序,作为哈希表的键
        
        // 将原始字符串 str 插入到哈希表中,键为排序后的 key
        //在 vector<string> 类型的值末尾添加一个新的元素(str),vector 是个动态数组
        hashTable[key].push_back(str); 
    }

    vector<vector<string>> result; // 存储最终结果

    for (auto& entry : hashTable) {
         // 遍历哈希表,将每个键对应的值(即一个字母异位词的分组)插入到结果数组中
        result.push_back(entry.second); 
    }

    return result;
}
  1. 算法推演
  • 输入数据:
    假设输入是以下字符串数组: vector strs = {"eat", "tea", "tan", "ate", "nat", "bat"};
  1. 初始化:

    首先,定义一个空的哈希表: unordered_map<string, vector> hashTable;

  2. 遍历输入字符串并构建哈希表:

    我们开始遍历 strs 数组,每次拿到一个字符串,然后对其进行处理。

  • 第一轮:

    处理字符串 "eat"

    "eat" 赋值给key。

    对 key 排序,得到 "aet"。

    在哈希表中查找 "aet",发现没有,所以自动创建新的键值对:hashTable["aet"] = ["eat"]。

    哈希表此时是: hashTable =

    {

    "aet": ["eat"]

    };

  • 第二轮:

    处理字符串 "tea"

    "tea" 赋值给key。

    对 key 排序,得到 "aet"。

    查找哈希表,发现 "aet" 已经存在,直接将 "tea" 加入对应的 vector:hashTable["aet"].push_back("tea")。

    哈希表此时是:hashTable =

    {

    "aet": ["eat", "tea"]

    };

  • 第三轮:

    处理字符串 "tan"

    "tan" 赋值给 key。

    对 key 排序,得到 "ant"。

    查找哈希表,发现 "ant" 不存在,自动创建新的键值对:hashTable["ant"] = ["tan"]。

    哈希表此时是: hashTable =

    {

    "aet": ["eat", "tea"],

    "ant": ["tan"]

    };

  • 第四轮:

    处理字符串 "ate"

    "ate" 赋值给 key。

    对 key 排序,得到 "aet"。

    查找哈希表,发现 "aet" 已经存在,直接将 "ate" 加入对应的 vector:hashTable["aet"].push_back("ate")。

    哈希表此时是:

    hashTable =

    {

    "aet": ["eat", "tea", "ate"],

    "ant": ["tan"]

    };

  • 第五轮:

    处理字符串 "nat"

    "nat" 赋值给 key。

    对 key 排序,得到 "ant"。

    查找哈希表,发现 "ant" 已经存在,直接将 "nat" 加入对应的 vector:hashTable["ant"].push_back("nat")。

    哈希表此时是:

    hashTable =

    {

    "aet": ["eat", "tea", "ate"],

    "ant": ["tan", "nat"]

    };

  • 第六轮:

    处理字符串 "bat"

    "bat" 赋值给 key。

    对 key 排序,得到 "abt"。

    查找哈希表,发现 "abt" 不存在,自动创建新的键值对:hashTable["abt"] = ["bat"]。

    哈希表此时是: hashTable =

    {

    "aet": ["eat", "tea", "ate"],

    "ant": ["tan", "nat"],

    "abt": ["bat"]

    };

  1. 构建结果: 接下来,我们遍历哈希表,将每组异位词添加到结果 result 中。
    vector<vector> result; for (auto& entry : hashTable) {
    result.push_back(entry.second); // 将每组异位词加入结果
    }
  • 遍历哈希表:

    第一组:

    entry.first = "aet", entry.second = ["eat", "tea", "ate"]。

    将 ["eat", "tea", "ate"] 添加到 result 中。

    第二组:

    entry.first = "ant", entry.second = ["tan", "nat"]。

    将 ["tan", "nat"] 添加到 result 中。

    第三组:

    entry.first = "abt", entry.second = ["bat"]。

    将 ["bat"] 添加到 result 中。

  • 最终 result 是: result =

    {

    {"eat", "tea", "ate"},

    {"tan", "nat"},

    {"bat"}

    };

  1. 返回结果: 函数返回 result,即字母异位词的分组。
  1. c++ 完整demo
cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <algorithm>

using namespace std;

vector<vector<string>> groupAnagrams(vector<string>& strs) {
    
    unordered_map<string, vector<string>> hashTable; // 定义哈希表

    //遍历输入的字符串数组
    for (const string& str : strs) {

        string key = str; //将当前字符串赋值给 key
        
        sort(key.begin(), key.end()); // 将字符串排序,作为哈希表的键
        
        // 将原始字符串 str 插入到哈希表中,键为排序后的 key
        //在 vector<string> 类型的值末尾添加一个新的元素(str),vector 是个动态数组
        hashTable[key].push_back(str); 
    }

    vector<vector<string>> result; // 存储最终结果

    for (auto& entry : hashTable) {

        result.push_back(entry.second); // 遍历哈希表,将每个键对应的值(即一个字母异位词的分组)插入到结果数组中
    }

    return result;
}

int main() {
    vector<string> strs = {"eat", "tea", "tan", "ate", "nat", "bat"};
    vector<vector<string>> result = groupAnagrams(strs);

    for (const auto& group : result) {
        for (const auto& word : group) {
            cout << word << " ";
        }
        cout << endl;
    }

    return 0;
}
相关推荐
Felix_12154 小时前
2025 西电软工数据结构机考 Tip (By Felix)
算法
未命名冀4 小时前
微服务面试相关
java·微服务·面试
飞yu流星5 小时前
C++ 函数 模板
开发语言·c++·算法
pursuit_csdn5 小时前
力扣 74. 搜索二维矩阵
算法·leetcode·矩阵
labuladuo5205 小时前
洛谷 P8703 [蓝桥杯 2019 国 B] 最优包含(dp)
算法·蓝桥杯·动态规划
Milk夜雨6 小时前
C语言冒泡排序教程简介
数据结构·算法·排序算法
委婉待续6 小时前
redis的学习(三)
数据结构·算法
一直学习永不止步7 小时前
LeetCode题练习与总结:随机翻转矩阵--519
java·数学·算法·leetcode·哈希表·水塘抽样·随机化
xiao--xin7 小时前
LeetCode100之组合总和(39)--Java
java·开发语言·算法·leetcode·回溯
YiHanXii7 小时前
Redis相关面试
数据库·redis·面试