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

题目描述:

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

示例:

输入: ["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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/450916.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【精心总结】java内存模型和多线程必会知识

内存模型 &#xff08;1&#xff09;java内存模型到底是个啥子东西&#xff1f; java内存模型是java虚拟机规范定义的一种特定模型&#xff0c;用以屏蔽不同硬件和操作系统的内存访问差异&#xff0c;让java在不同平台中能达到一致的内存访问效果&#xff0c;是在特定的协议下…

工作流 activity 视频教程 + redis 视频教程 百度网盘分享地址

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 云盘下载都没有密码&#xff0c;直接下载&#xff0c;解压有密码&#xff1a;chongxiangmengxiangjiaoyu&#xff0c; 解压完成后就可以…

快速解决 GRADLE 项目下载 gradle-*-all.zip 慢的问题

1、首先根据项目中 gradle\wrapper\gradle-wrapper.properties 文件的 distributionUrl 属性的值 #Tue Feb 06 12:27:20 CET 2018 distributionBaseGRADLE_USER_HOME distributionPathwrapper/dists zipStoreBaseGRADLE_USER_HOME zipStorePathwrapper/dists distributionUrlht…

[Python] 程序结构与控制流

1. 条件语句 if、else与elif语句用于控制条件代码的执行。条件语句的一般格式如下&#xff1a; if expression:statements elif expression:statements elif expression:statements ... else:statements 如果不需要执行任何操作&#xff0c;可以省略条件语句的else和elif子句。…

webrtc 源码结构

apiWebRTC 接口层。包括 DataChannel, MediaStream, SDP相关的接口。各浏览器都是通过该接口层调用的 WebRTC。call存放的是 WebRTC “呼叫&#xff08;Call&#xff09;” 相关逻辑层的代码。audio存放音频网络逻辑层相关的代码。音频数据逻辑上的发送&#xff0c;接收等代码。…

mysql查询流程解析及重要知识总结

时光荏苒啊&#xff01;在过两个月我就工作满三年了&#xff0c;大学毕业的情景还历历在目&#xff0c;而我已经默默的向油腻中年大叔进发了。作为一名苦逼的后端工程师&#xff0c;我搞过一段时间python&#xff0c;现在靠java糊口&#xff0c;但后来才发现&#xff0c;始终不…

界面无小事(八):RecyclerView增删item

界面无小事(一): RecyclerViewCardView了解一下 界面无小事(二): 让RecyclerView展示更多不同视图 界面无小事(三):用RecyclerView Toolbar做个文件选择器 界面无小事(四):来写个滚动选择器吧! 界面无小事(五):自定义TextView 界面无小事(六):来做个好看得侧拉菜单! 界面无小事…

Failed to install Tomcat7 service 解决

见&#xff1a; http://blog.csdn.net/desow/article/details/21446197 tomcat 安装时出现 Failed to install Tomcat7 service 今天在安装tomcat时提示 Failed to install Tomcat7 service了&#xff0c;花了大半天的时间找到了原因&#xff0c;下面分享给大家&#xff0c;希望…

保守官僚 诺基亚就这样迷失在智能机时代?

7月19日&#xff0c;诺基亚发布了二季度财报&#xff0c;净亏损达到了17亿美元&#xff0c;其中智能手机份额和销售量进一步下滑&#xff0c;这个智能手机的领导者&#xff0c;正在因智能手机而急速坠落。诺记亚领先业界近十年就把握住了智能手机的趋势&#xff0c;并推出了首款…

django集成ansibe实现自动化

动态生成主机列表和相关参数 def create_admin_domain(admin_node):workpath BASE_DIR /tools/ansible/scripthosts_file BASE_DIR /tools/ansible/host/ createhostfile()yml_file BASE_DIR /tools/ansible/yml/ create_admin_domain.ymldomain_path admin_node.doma…

extend 对象继承

function extend(o, n, override) {for (var p in n) {if (n.hasOwnProperty(p) && (!o.hasOwnProperty(p) || override))o[p] n[p];} }// 默认参数 var options {pageIndex: 1,pageTotal: 2 };// 新设置参数 var userOptions {pageIndex: 3,pageSize: 10 }extend(o…

【spring容器启动】之bean的实例化和初始化(文末附:spring循环依赖原理)

本次我们通过源码介绍ApplicationContext容器初始化流程&#xff0c;主要介绍容器内bean的实例化和初始化过程。ApplicationContext是Spring推出的先进Ioc容器&#xff0c;它继承了旧版本Ioc容器BeanFactory&#xff0c;并进一步扩展了容器的功能&#xff0c;增加了bean的自动识…

如何将自己的Java项目部署到外网

见&#xff1a;http://jingyan.baidu.com/article/90bc8fc864699af653640cf7.html 做b/s模式的web开发不同于c/s模式的客户端开发&#xff0c;c/s模式我们只要做好生成可执行文件发送给其他人&#xff0c;其他人就可以用了。但是c/s模式不同&#xff0c;在同一局域网下&#xf…

[Swift]LeetCode916.单词子集 | Word Subsets

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号&#xff1a;山青咏芝&#xff08;shanqingyongzhi&#xff09;➤博客园地址&#xff1a;山青咏芝&#xff08;https://www.cnblogs.com/strengthen/&#xff09;➤GitHub地址&a…

揭秘腾讯研究院输出策略:产品和人才的孵化器

直到现在&#xff0c;腾讯研究院创始人郑全战仍坚持面试招入研究院的每一个人&#xff0c;并做详细记录。天赋上的灵性、性格中的包容是他看重的&#xff0c;当然首先人要踏实。大约6年前&#xff0c;郑全战加入腾讯&#xff0c;负责筹建中国互联网公司中的第一个研究院&#x…

java后端必会【基础知识点】

&#xff08;一&#xff09;java集合类&#xff08;done&#xff09; 在java集合类中最常用的是Collection和Map的接口实现类。Collection又分为List和Set两类接口&#xff0c;List的实现类有ArrayList、LinkedList、Vector、Stack&#xff0c;Set接口的实现类有HashSet、Tree…

无法连接虚拟设备ide1:0,主机上没有相对应的设备... 解决

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 运行虚拟机出现报错&#xff1a; 无法连接虚拟设备ide1:0&#xff0c;主机上没有相对应的设备&#xff0c;您 要在每次开启此虚拟机时都…

缴满15年能领多少钱 养老金计算公式网上疯传

社保人员称我省计算方式与各设区市平均工资挂钩&#xff0c;与网上不同 最近&#xff0c;关于“延迟退休”引起各方高度关注&#xff0c;成为广大居民十分关心的话题。是否延迟退休尚无定论&#xff0c;但在网上有不少关于养老金的计算。那网上流传的计算方法是否科学&#xff…

48_并发编程-线程-资源共享/锁

一、数据共享多个线程内部有自己的数据栈&#xff0c;数据不共享&#xff1b;全局变量在多个线程之间是共享的。1 # 线程数据共享不安全加锁2 3 import time4 from threading import Thread, Lock5 6 7 num 1008 9 def func(t_lock): 10 global num 11 t_lock.acquire…

移动硬盘提示无法访问设备硬件出现致命错误,导致请求失败的资料寻回方案

J盘打不开设备硬件出现致命错误,导致请求失败&#xff0c;是因为这个I盘的文件系统内部结构损坏导致的。要恢复里面的数据就必须要注意&#xff0c;这个盘不能格式化&#xff0c;否则数据会进一步损坏。具体的恢复方法看正文 工具/软件&#xff1a;星空数据恢复软件 步骤1&…