LeeCode_49. 字母异位词分组(优先队列+哈希)

一、介绍

1.题目描述

题目链接:https://leetcode-cn.com/problems/group-anagrams/

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

字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母都恰好只用一次。

2.测试样例

["eat", "tea", "tan", "ate", "nat", "bat"]
# [["bat"],["nat","tan"],["ate","eat","tea"]]

[""]
# [[""]]

["a"]
# [["a"]]

["","b",""]
# [["b"],["",""]]

["ac","c"]
# [["c"],["ac"]]

["ddddddddddg","dgggggggggg"]
# [["dgggggggggg"],["ddddddddddg"]]

二、题解

该方法如果用暴力实现,将达到n²的复杂度,必定会超时,因此需要考虑别的解决方案。

所想到的是优先队列或哈希

如果想单独处理空字符串,可以使用以下代码

// 清除并记录""
vector<vector<string>> ans;
int t=0;  // t 标记是否出现过""
vector<string>::iterator it = strs.begin();
while(it != strs.end()){
    if(*it==""){  // 如果有""
        if(t==0){
            ans.push_back(vector<string>());
            t=1;
        }  // 插入答案并删除""
        ans[0].push_back(*it);
        strs.erase(it);
    }
    else it++;
}

1、优先队列🟢

由于优先队列可以实现对插入的元素排序,可以想到

1、先对每个字符串的内部字符排序

2、再对字符串进行串间排序,就可以得到各个字符组成相同的字符串个数。

  • 需要同时存储字符串和其下标。

  • 字符串,串内按字符排序代码:

    sort(string.begin(),string.end())
    

以[“eat”, “”, “tan”, “ate”, “bat”]为例

  • 遍历,对字符串按字符排序(eat→aet)
  • 将串内排序后的字符串和其在原数组中的下标(aet:0,"":1,ant:2,aet:3,abt:4)一起插入优先队列,得到优先队列 (ant:2,aet:3,aet:0,abt:4,"":1)
  • 创建结果数组,插入第一个元素 [[“tan”]]。
  • 遍历接下来的元素
    • aet与ant不同,将原字符串插入新数组,得到[[“tan”],[“ate”]]
    • aet与aet相同,将原字符串插入当前数组,得到 [[“tan”],[“ate”,“eat”]]
    • ……
  • 得到答案[[“tan”],[“ate”,“eat”],[“bat”],[""]]
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        vector<vector<string>> ans;
        int n=strs.size();
        int index=0,t=0;
        priority_queue<pair<string,int>> q;  // 优先队列,存储(字符串,在原数组中下标)
        for(int i=0;i<n;i++){
            string temp=strs[i];
            sort(temp.begin(),temp.end());  // 串内按字符排序
            q.emplace(temp,i);  // 利用优先队列进行串间排序并记录下标
        } 
        // 插入第一个答案
        string temp=q.top().first;
        ans.push_back(vector<string>());
        ans[index].push_back(strs[q.top().second]);
        q.pop();
        while(!q.empty()){
            if(temp==q.top().first){  // 同样的字符串插入同一个数组
                ans[index].push_back(strs[q.top().second]);
            }
            else{  // 如果不同,加入新数组
                temp=q.top().first;
                ans.push_back(vector<string>());
                ans[++index].push_back(strs[q.top().second]);
            }
            q.pop();  // 处理队头后弹出
        }
        return ans;
    }
};

image-20210920204917514

2、哈希🟡

第二种方法是使用哈希映射。对每个字符串进行串内排序后,遍历每个字符串

  • 若该字符串未出现,将加入map,记录对应的答案数组中的下标
  • 若该字符串出现过,在map对应的下标数组中插入该串的原字符串

以[“eat”, “”, “tan”, “ate”, “bat”]为例

  • 遍历,对当前字符串按字符排序(eat→aet)
    • aet未在map中,map[aet]=0,数组第0行插入原字符串eat,答案数组[[“eat”]]
    • ““未在map中,map[””]=1,数组第1行插入原字符串"",答案数组[[“eat”],[""]]
    • ant未在map中,map[tan]=2,数组第2行插入原字符串tan,答案数组[[“eat”],[""],[“tan”]]
    • aet在map中,因为map[aet]=0,数组第0行插入原字符串ate,答案数组[[“eat”,“ate”],[""],[“tan”]]
    • ……
  • 得到答案[[“eat”,“ate”],[""],[“tan”],[“bat”]]

参考链接:https://www.cnblogs.com/caiyishuai/p/15313213.html

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        vector<vector<string>> ans;
        string temp;
        map<string,int> map;
        int n=strs.size(),index=0;
        for(int i=0;i<n;i++){
            temp=strs[i];
            sort(temp.begin(),temp.end());  // 串内按字符排序
            if(map.count(temp)){       // 如果map中已有,存储对应数组
                ans[map[temp]].push_back(strs[i]);
            }
            else{   // 若没有,创建数组,添加map映射
                map[temp]=index;
                ans.push_back(vector<string>());
                ans[index++].push_back(strs[i]);
            }
        }
        return ans;
    }
};

image-20210920195252531

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值