leetcode之hot100---字母异位词分组(C++)

1.思路一:将字符串按照统一的(从小到大)规则进行排序,以排序后的字符串为键借助哈希表进行分组

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        //定义一个哈希表用于存放结果
        unordered_map<string, vector<string>> ht;

        //使用迭代器遍历字符串数组strs
        for(auto &it: strs){
            string sorted_s = it;//将每一个字符串进行复制
            ranges::sort(sorted_s);//对复制的字符串进行从小到大排序
            //sort(sorted_s.begin(), sorted_s.end());
            ht[sorted_s].push_back(it);//将排序后字符串相等的字符串分到同一组,
                                    //即以排序后的字符串为键,以原字符串组成的列表为值
            //ht[sorted_s].emplace_back(it);

        }
        
        vector<vector<string>> a;//构建一个新容器a用于存放结果
        a.reserve(ht.size());//预留和哈希表中值相等的空间
        //将哈希表ht中的值部分提取出来
        for(auto it = ht.begin(); it != ht.end(); it++){
            a.push_back(it->second);
        }
        // for (auto &[_, v] : ht) {
        //     a.push_back(v);
        // }
        return a;
        
    }
};

针对相似函数的解释:

push_back()与emplace_back()

两者都适用于向支持动态扩展的容器的末尾增加一个元素,如 std::vectorstd::deque,

但是

  • push_back()

    • 接受一个现有对象作为参数。

    • 需要将提供的对象拷贝(或移动)到容器中。

    • 对于复杂类型,存在不必要的性能开销。

  • emplace_back()

    • 接受构造函数的参数,直接在容器末尾构造对象。

    • 避免了临时对象的创建和拷贝。

    • 对于复杂类型,效率更高。

当你已经有了一个现成的对象,并希望将其添加到容器时使用push_back()

当你希望直接构造一个对象,并将其添加到容器时使用emplace_back()

以下是一个自定义类型中两函数的对比示例:

    vector<Person> people;

    // 使用 push_back()
    Person p1("Alice", 30);
    people.push_back(p1); // 需要调用拷贝构造函数

    // 使用 emplace_back()
    people.emplace_back("Bob", 25); // 直接构造对象

 for (auto &[_, value] : m)与for(auto it = ht.begin(); it != ht.end(); it++)

前者使用结构化绑定(C++17 引入),不需要显式调用迭代器,可以直接访问键和值,并进行修改:

  • unordered_map 的每个元素(键值对)解构为键和值的引用:
    • _:占位符表示键(可以命名为其他变量名)。
    • value:引用表示值(可以直接操作值)。

后者通过迭代器手动遍历容器,每个 it 是指向容器元素(键值对)的迭代器。

  • 访问键和值

    • 使用 it->first 访问键。
    • 使用 it->second 访问值。

 2.思路二:遍历字符串数组,记录每个字符串中26个字母出现的次数,以26个字母出现的次数为键借助哈希表进行分组

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        //思路:记录26个字母在每个字符串中出现的次数,借助哈希表进行分组
        unordered_map<string, vector<string>> ht;

        for(auto &s: strs){//使用迭代器访问字符串数组

           //定义一个count数组记录26个字母出现的次数
            int count[26] = {0};
            for(auto &e: s){//使用迭代器访问每一个字符串
                count[e-'a']++;
            }
            //定义一个字符串将26个字母出现次数统计起来
            string key = "";
            for(int i = 0; i < 26; i++){
                if(count[i] != 0){
                    key.push_back('a'+i);
                    key.push_back(count[i]);
                }
            }
            //以26个字母出现次数为键,以字符串为值插入哈希表       
            ht[key].push_back(s);
        }

        vector<vector<string>> r;
        r.reserve(ht.size());
    
        for(auto it = ht.begin(); it != ht.end(); it++){
            r.push_back(it->second);
        }
        return r;
    }
};

总结: 以上两种方法都是使用的哈希表,只是表的键不同,键还可以是其他内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值