LeetCode 热题 100——2.字母异位词分组

🧑‍💻博主名称:鱼子星_

✅数据结构专栏:【数据结构】

✅算法竞赛专栏:【算法竞赛】

✅C++系列专栏:【C++从零开始系列】


2. 字母异位词分组

【LeetCode 49.字母异位词分组】

题目描述

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


样例

示例 1:

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

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

解释:

  • 在 strs 中没有字符串可以通过重新排列来形成 "bat"。
  • 字符串 "nat" 和 "tan"是字母异位词,因为它们可以重新排列以形成彼此。
  • 字符串 "ate" ,"eat" 和 "tea"是字母异位词,因为它们可以重新排列以形成彼此。

示例 2:

输入: strs = [""]

输出: [[""]]

示例 3:

输入: strs = ["a"]

输出: [["a"]]


解题思路

💡解法一:排序 + 哈希表

不管异位排列的字符串有多少个样式,对它们单独排序完之后,都是一样的字符串。例如:["ate","eat","tea"] 排序完成后都是 "aet"

所以,可以遍历字符串数组,对每个字符串单独的排序后,插入到哈希表中,最后将哈希表中的所有元素插入到要返回的二维数组中即可。

🗋 代码

cpp 复制代码
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> mp;
        for(int i = 0; i < strs.size(); i++)
        {
            string s = strs[i];
            sort(s.begin(), s.end());
            mp[s].push_back(strs[i]);
        }
        vector<vector<string>> ret;
        for(auto t : mp)
        {
            ret.push_back(t.second);
        }
        return ret;
    }
};

LeetCode官方代码

cpp 复制代码
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> mp;
        for (string& str: strs) {
            string key = str;
            sort(key.begin(), key.end());
            mp[key].emplace_back(str);
        }
        vector<vector<string>> ans;
        for (auto it = mp.begin(); it != mp.end(); ++it) {
            ans.emplace_back(it->second);
        }
        return ans;
    }
};

提交结果

💡解法二:计数 + 哈希表

不管排列的方式有多少种,只要组成相同的字符串,它们 26 个字母出现的次数肯定是相同的,只需要使用数组记录每个字符串 26 个字母出现的次数,将相同的分在一起就可以了

🗋 代码

cpp 复制代码
class Solution {
public:
    string calc(string& s, vector<int>& a)
    {
        string t = "";
        for(int i = 0; i < s.size(); i++)
        {
            int t = s[i] - 'a';
            a[t]++;
        }
        for(int i = 0; i < 26; i++) t.push_back(a[i] + '0');
        return t;
    }
    
    vector<vector<string>> groupAnagrams(vector<string>& strs) 
    {
        int n = strs.size();
        unordered_map<string, int> mp;
        
        //给哈希表开辟空间
        vector<vector<int>> hash(n);
        for(int i = 0; i < n; i++)
            hash[i].resize(26);
        //填表
        int cnt = 0;
        vector<vector<string>> ret;
        for(int i = 0; i < n; i++)
        {
            string t = calc(strs[i], hash[i]);
            if(mp.count(t)){
                ret[mp[t]].push_back(strs[i]);
            }else{
                mp[t] = cnt++;
                vector<string> st;
                st.push_back(strs[i]);
                ret.push_back(st);
            }
        }
        return ret;
    }
};

LeetCode官方代码

cpp 复制代码
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        // 自定义对 array<int, 26> 类型的哈希函数
        auto arrayHash = [fn = hash<int>{}] (const array<int, 26>& arr) -> size_t {
            return accumulate(arr.begin(), arr.end(), 0u, [&](size_t acc, int num) {
                return (acc << 1) ^ fn(num);
            });
        };

        unordered_map<array<int, 26>, vector<string>, decltype(arrayHash)> mp(0, arrayHash);
        for (string& str: strs) {
            array<int, 26> counts{};
            int length = str.length();
            for (int i = 0; i < length; ++i) {
                counts[str[i] - 'a'] ++;
            }
            mp[counts].emplace_back(str);
        }
        vector<vector<string>> ans;
        for (auto it = mp.begin(); it != mp.end(); ++it) {
            ans.emplace_back(it->second);
        }
        return ans;
    }
};

提交结果