字母异位词分组(每天刷力扣hot100系列)

题目介绍:

方法1:遍历法

cpp 复制代码
#include <algorithm>

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) 
    {
        vector<string> beg(strs);
        for (string& k : beg) 
            sort(k.begin(), k.end());  // 排序作为键

        vector<vector<string>> rel;
        vector<bool> visited(strs.size(), true);  // 使用visited标记

        for(int i=0;i<beg.size();i++)
        {
            vector<string> temp;
            if(visited[i]==true)
            {
                temp.push_back(strs[i]);
                for(int j=i+1;j<beg.size();j++)
                {
                    if(beg[i]==beg[j])
                    {
                        temp.push_back(strs[j]);
                        visited[j]=false;
                    }
                }
                rel.push_back(temp);
            }

        }
        return rel;
    }
};

(博主自己敲的方法,不推荐,适合理解)

代码思路

  1. 创建beg数组,是strs的拷贝,然后对beg中的每个字符串进行排序(这样同一个变位词组排序后字符串相同)。

  2. 然后遍历beg数组,对于每个字符串,如果它是true,则创建一个临时组,将当前字符串加入(注意:这里加入的是排序后的字符串,但实际需要的是原字符串)。 3. 然后内层循环从i+1开始,找后面所有与beg[i]相同的字符串,将对应的原字符串(strs[j])加入临时组,并将beg[j]标记为false(表示已经处理过)。

  3. 最后将临时组加入结果rel中。

方法2:哈希桶

cpp 复制代码
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) 
    {
        //哈希桶
        unordered_map<string,vector<string>> mp;//创建一个字符串和字符串数组对应键值的哈希表
        for(auto str:strs)//迭代器将数组里的字符串全部排序,然后在对应的字符串键处存放原字符串
        {
            string key=str;
            sort(key.begin(),key.end());
            mp[key].push_back(str);//这里如果用emplace_back内存消耗更少
        }

        vector<vector<string>> rel;
        for(auto it=mp.begin();it!=mp.end();it++)//遍历哈希桶
        {
            rel.push_back(it->second);//将字符串组插入rel中,这里如果用emplace_back内存消耗更少
        }
        return rel;
    }
};

复杂度分析

1.时间复杂度O(nklogk),其中 n 是 strs 中的字符串的数量,k 是 strs 中的字符串的的最大长度。需要遍历 n 个字符串,对于每个字符串,需要 O(klogk) 的时间进行排序以及 O(1) 的时间更新哈希表,因此总时间复杂度是 O(nklogk)。

2.空间复杂度O(nk),其中 n 是 strs 中的字符串的数量,k 是 strs 中的字符串的的最大长度。需要用哈希表存储全部字符串。

核心区别

特性 push_back() emplace_back()
工作原理 构造临时对象 → 拷贝/移动到容器 直接在容器内存中构造对象
参数 接受对象本身 接受对象的构造参数
效率 可能额外构造临时对象(有拷贝开销) 避免临时对象(更高效)
适用场景 添加已存在的对象 直接构造新对象

这个方法不同的是不需要根据每个的字符串往后遍历,而是直接放进哈希桶,最后把vector<string>提出来就行。

力扣上还有个计数的方法比较复杂,但是时间复杂度和空间复杂度进一步降低了:

方法3:计数

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;
    }
};

复杂度分析

1.时间复杂度:O(n(k+∣Σ∣)),其中 n 是 strs 中的字符串的数量,k 是 strs 中的字符串的的最大长度,Σ 是字符集,在本题中字符集为所有小写字母,∣Σ∣=26。需要遍历 n 个字符串,对于每个字符串,需要 O(k) 的时间计算每个字母出现的次数,O(∣Σ∣) 的时间生成哈希表的键,以及 O(1) 的时间更新哈希表,因此总时间复杂度是 O(n(k+∣Σ∣))。

2.空间复杂度:O(n(k+∣Σ∣)),其中 n 是 strs 中的字符串的数量,k 是 strs 中的字符串的最大长度,Σ 是字符集,在本题中字符集为所有小写字母,∣Σ∣=26。需要用哈希表存储全部字符串,而记录每个字符串中每个字母出现次数的数组需要的空间为 O(∣Σ∣),在渐进意义下小于 O(n(k+∣Σ∣)),可以忽略不计。

喜欢的话就关注我吧~~~求关注求赞求收藏~~~^-^

相关推荐
云天徽上21 分钟前
【数据可视化-96】使用 Pyecharts 绘制主题河流图(ThemeRiver):步骤与数据组织形式
开发语言·python·信息可视化·数据分析·pyecharts
jdlxx_dongfangxing32 分钟前
C++ 序列式容器深度解析:vector、string、deque 与 list
c++·stl
欧阳小猜1 小时前
深度学习②【优化算法(重点!)、数据获取与模型训练全解析】
人工智能·深度学习·算法
小欣加油1 小时前
leetcode 904 水果成篮
c++·算法·leetcode
有Li1 小时前
CXR-LT 2024:一场关于基于胸部X线的长尾、多标签和零样本疾病分类的MICCAI挑战赛|文献速递-深度学习人工智能医疗图像
论文阅读·人工智能·算法·医学生
quaer2 小时前
print(2 ** 3)
开发语言·python
君万2 小时前
【LeetCode每日一题】56. 合并区间
算法·leetcode·golang
墩墩同学2 小时前
【LeetCode题解】LeetCode 287. 寻找重复数
算法·leetcode·二分查找
Elieal2 小时前
Java 链表完全指南:从基础到力扣简单题实战
java·leetcode·链表
小南家的青蛙2 小时前
LeetCode第55题 - 跳跃游戏
算法·leetcode·职场和发展