题目描述:

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

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

说明:

  • 所有输入均为小写字母。
  • 不考虑答案输出的顺序。

    给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

    示例:

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

    说明:

    • 所有输入均为小写字母。
    • 不考虑答案输出的顺序。

要完成的函数:

vector<vector<string>> groupAnagrams(vector<string>& strs)

说明:

1、给定一个vector,里面装着多个string,要求把这些string进行分组。

两个字符串拥有相同的字母,就是同一组。(题目说字母相同,顺序不同,但测试样例中出现了字母相同顺序也相同的,也在同一组)

字符串只含有小写字母。

每一组存在一维vector中,所有组存放在二维vector中,最终返回二维vector。

2、这道题笔者最开始想用一个双重循环,外层循环对每个字符串进行迭代,内层循环判断当前字符串跟前面的字符串,有没有哪个是相同字母的。

关于内层循环的判断,笔者最开始想用异或来处理,但后来发现it和ro这四个不同的字母,i^t^r^o的结果为0……

也就是我们不能用异或结果是不是0来判断字母是不是相同。

异或应该只是适用于只有一个字母不同,而其他字母都相同的情况。

那不能用异或,那就用普通的“空间换时间”,我们建立长度为26的vector,在内层循环中判断两个字符串是否拥有相同字母。

在对长度为26的vector进行操作前,我们先判断两个字符串的长度是否相等,这可以省去很多时间。

代码如下:(附详解)

    bool judge(string a,string b)//判断两个字符串是否拥有相同的字母{vector<int>table(26,0),t1(26,0);for(char i:a)table[i-'a']++;for(char i:b)table[i-'a']--;if(table!=t1)return false;//如果table不是全为0,返回falsereturn true;//否则返回true}vector<vector<string>> groupAnagrams(vector<string>& strs) {vector<vector<string>>res={{strs[0]}};//初始化最终要返回的二维vectorbool flag;for(int i=1;i<strs.size();i++)//循环迭代每个字符串{flag=0;for(int j=0;j<res.size();j++)//对当前的字符串,判断是否跟前面出现过的字符串,拥有相同字母{if(strs[i].size()!=res[j][0].size())//长度的判断continue;if(judge(strs[i],res[j][0]))//字母相同的两个字符串{res[j].push_back(strs[i]);flag=1;break;}}if(flag==0)//前面所有字符串跟当前字符串的字母都不相同{res.push_back({strs[i]});}}return res;//最终返回res}

上述代码也可以通过测试,但是实测1228ms,beats 2.20% of cpp submissions……太低了

那肯定还有更好的办法==

我们分析一下上述代码,发现耗费时间的地方在于:

①双重循环,如果可以改成单重循环就最好了。

②二维vector的不断申请空间、不断插入

第二点似乎很难避免,我们要初始化res拥有多长的长度?跟给定的一维vector strs一样长?那多出来那部分怎么处理……

不断地pop_back()?这也是一个方法,但看了一下普遍的时间花费是36ms左右,我这样改可能效果也不会很大……

那第一点要怎么改善?外层循环肯定不可少了,内层循环改成O(1)的时间复杂度?

我们想一下,如果是数字串而不是字母串,我们会怎样判断当前数字串有没有出现过?

比如12,32,12,当前数字是第三个数字12,我们可以用vector,前面有了vector[12]=1,vector[32]=1,此时我们再查询一下当前数字12的对应vector[12],是不是0。

如果是0,那么没有出现过,如果不是0,那么出现过。

这个时候我们不用一个个地去循环,去遍历,直接就访问了。

那可不可以同样利用这种方法来处理字母串呢?

答案是可以的,我们可以用哈希表。

哈希表其实就是数组+链表的结构,在c++中,笔者觉得map这种数据结构可能就是实现了哈希表的算法。

哈希表结合了数组的快速访问、修改和链表的无限长度两个特点,可以参考下面这张图。

左边是数组,快速访问和修改,右边的链表延伸出去,无限长度。

我们以字母串作为键值,像用vector查看数字串一样去判断。

但有的同学可能有想法,比如“ate”和“eat”这两个键值都不一样,你怎么判断?

“ate”和“eat”是不一样,但它们有共性,那就是拥有的字母相同,我们可以对它们的字母排下序,就可以转化为相同的键值了。

代码如下:(附详解)

    vector<vector<string>> groupAnagrams(vector<string>& strs) {vector<vector<string>>res;//最终要返回的二维vectorunordered_map<string,int>m1;//定义一个map作为哈希表int index=0;vector<string> strs1=strs;//用于重新排序strs中的每个字符串,strs是原本for(int i=0;i<strs1.size();i++){sort(strs1[i].begin(),strs1[i].end());//对字符串中的字母进行排序if(!m1.count(strs1[i]))//如果之前没有出现过{m1[strs1[i]]=index;//更新一下index++;//index作为res中的索引res.push_back({strs[i]});//插入一个一维的vector}else//如果有出现过了{res[m1[strs1[i]]].push_back(strs[i]);//res找到对应的索引,插入当前字符串}}return res;//最终返回res}

上述代码实测28ms,beats 93.68% of cpp submissions。

哈希表其实就是我们平时常用的vector的升级版本,用map实现时,既可以实现快速访问,又有好的哈希函数,使得空间充足。

神奇神奇~

转载于:https://www.cnblogs.com/chenjx85/p/9477896.html

leetcode-49-字母异位词分组(神奇的哈希)相关推荐

  1. leetcode 49. 字母异位词分组

    49. 字母异位词分组 - 力扣(LeetCode) 一开始想的是把各个字符串中每个字符ascii码值相加,然后相同的ascii码值放在一个组,在相同的ascii码值组中再去细找字母异位词. 一开始算 ...

  2. LeetCode 49字母异位词分组50pow(x,n)51八皇后

    原创公众号:bigsai 如果不错记得点赞收藏! 关注回复 bigsai 领取Java进阶pdf资源,回复进群加入力扣打卡群. 上周打卡内容:43字符串相乘&44通配符匹配 45跳跃游戏&am ...

  3. LeetCode 49. 字母异位词分组(哈希)

    1. 题目 给定一个字符串数组,将字母异位词组合在一起.字母异位词指字母相同,但排列不同的字符串. 示例:输入: ["eat", "tea", "ta ...

  4. leetcode 49. 字母异位词分组(排序+hash)

    给定一个字符串数组,将字母异位词组合在一起.字母异位词指字母相同,但排列不同的字符串. 示例: 输入: ["eat", "tea", "tan&quo ...

  5. LeetCode 49. 字母异位词分组 Group Anagrams

    给定一个字符串数组,将字母异位词组合在一起.字母异位词指字母相同,但排列不同的字符串. 示例: 输入: ["eat", "tea", "tan&quo ...

  6. LeetCode 49 字母异位词分组

    力扣 思路:哈希表: 排序:对两个字符串分别进行排序之后得到的字符串是相同的 将排序之后的字符串作为哈希表的键     (参考LeetCode官方题解)  定义哈希表 unordered_map< ...

  7. 【LeetCode】【HOT】49. 字母异位词分组(递归)

    [LeetCode][HOT]49. 字母异位词分组 文章目录 [LeetCode][HOT]49. 字母异位词分组 package hot;import java.util.ArrayList; i ...

  8. Leetcode刷题100天—49. 字母异位词分组( 排序)—day37

    前言: 作者:神的孩子在歌唱 大家好,我叫运智 49. 字母异位词分组 难度中等847收藏分享切换为英文接收动态反馈 给你一个字符串数组,请你将 字母异位词 组合在一起.可以按任意顺序返回结果列表. ...

  9. 【LeetCode】49.字母异位词分组 (三种解法开拓思路,java实现)

    49. 字母异位词分组 分析 方法一:排序数组分类 思路 当且仅当它们的排序字符串相等时,两个字符串是字母异位词. 算法 维护一个映射 ans : {String -> List},其中每个键 ...

  10. 49. 字母异位词分组

    49. 字母异位词分组 给你一个字符串数组,请你将 字母异位词 组合在一起.可以按任意顺序返回结果列表. 字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母都恰好只用一次. 示例 ...

最新文章

  1. 周鸿祎的“加法”和“减法”
  2. c语言atoll函数怎么用_C ++中带有示例的atoll()函数
  3. ASP.NET MVC中如何在客户端进行必要的判断
  4. python颜色列表代码seaborn_在Python中Seaborn – 根据色调名称更改条形颜色
  5. fastadmin绑定edit.html,FAST-ADMIN 根据生成命令行修改页面
  6. python实现一个简单的【图像中物体坐标】标注小工具
  7. mybatis中resultMap的几种用法
  8. Android studio 设置默认打开项目,默认打开项目方式
  9. 关于vs编译器的一些认识
  10. pe怎么看计算机mac地址,Win10查看本机mac地址方法|电脑mac地址怎么查
  11. 文件追加 c语言,c语言追加方式想文件里面写东西
  12. 该来的年终总结,还是来了
  13. 历史不忍细看之--孔老二罪恶的一生
  14. 前端做大屏显示,缩放比,分辨率怎样适配?
  15. 微信公众号获取定位地图(有经纬度)
  16. Datawhale组队学习NLP之transformer Task 01
  17. 设计标志性专辑封面的 5 个技巧
  18. java的JVM虚拟机相关知识,简单易懂。
  19. css3自定义字体、字体图标
  20. mysql优化工具 MySQL Tuner

热门文章

  1. php fast cgi nginx,通过fast-cgi连接php-fpm和nginx之间的连接是持久的(保持活动)连接吗?...
  2. oracle推送短信,ORACLE 10G如何实现发短信的服务?
  3. leetcode259. 较小的三数之和
  4. C++:30 ---C++类成员,成员函数的内存布局
  5. (二)深入浅出TCPIP之再识TCP,理解TCP三次握手(上)
  6. 我对STL的一些看法(二)认识vector容器
  7. 机器学习问题总结(05)
  8. 《Python Cookbook 3rd》笔记(4.12):不同集合上元素的迭代
  9. Web3.js 学习
  10. Android Studio 快捷键大全(Mac系统)