2020-10-21 第2题

it2024-01-15  60

2020-10-21 第2题

题目来源:leetcode 每日一题

925. 长按键入

你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。

你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回 True。

示例 1: 输入:name = “alex”, typed = “aaleex” 输出:true 解释:‘alex’ 中的 ‘a’ 和 ‘e’ 被长按。 示例 2: 输入:name = “saeed”, typed = “ssaaedd” 输出:false 解释:‘e’ 一定需要被键入两次,但在 typed 的输出中不是这样。 示例 3: 输入:name = “leelee”, typed = “lleeelee” 输出:true 示例 4: 输入:name = “laiden”, typed = “laiden” 输出:true 解释:长按名字中的字符并不是必要的。 提示: name.length <= 1000 typed.length <= 1000 name 和 typed 的字符都是小写字母。

  今天没有像昨天一样直接去看别人的题解,忍住了。这个题在简单的类别里,我好奇是怎么划分这三个类别的。

我觉得一开始我的思路有很多,但是很乱,最后我选了一个最容易理清楚的写:   用两个游标,一个指当前字母,一个指后一个字母,两两一组,在typed字符串中如果能找到和name字符串出现顺序相同的两个字符就说明这一组成功,flag++(最后flag的值应该是name字符串的长度-1 ,如果想提高效率,可能加上一句,如果找不到直接退出会更快,一会儿试试----------------试完了,时空复杂度反倒下降了,不懂)。   写完以后报错了,因为两种情况没有考虑:   1、alex-alexxr(末尾多字符)   2、alex-ssalex(开头多字符)   我因为懒得想太多就直接加了两个判断,开头第一个字符必须和name[0]相同,结尾所有字符必须和name[name_len-1]相同。      

class Solution { public: bool isLongPressedName(string name, string typed) { int name_len=name.size(); int typed_len=typed.size(); int flag=0,i,j,vernier=0; char ver_pre,ver_cur,tmp_cur,tmp_pre,tail; for(i=0;i<name_len-1;i++) { ver_pre=name[i]; ver_cur=name[i+1]; for(j=vernier;j<typed_len;j++) { tmp_pre=typed[j]; tmp_cur=typed[j+1]; if(tmp_pre==ver_pre&&tmp_cur==ver_cur) { flag++; vernier=j+1; break; } //else if(j+1==typed_len) //return false;(不知道为什么加了这个时空复杂度反倒下降了......) } } if(flag!=name_len-1) return false; else { //flag=0; tail=name[name_len-1]; for(i=vernier;i<typed_len;i++) { if(typed[i]!=tail) return false; } if(name[0]!=typed[0]) return false; return true; } } };

运行结果如下,我其实不明白为什么运行第二遍效率涨了这么多,这到底是怎么算的?

一会儿吃饭回来看别人的题解。不过代码长度和运行时间好像没什么太大的关系。

class Solution { public: bool isLongPressedName(string name, string typed) { int j=0; for(int i=0;i<typed.size();i++){ if(j==name.size()||typed[i]!=name[j]) { if(i==0||typed[i]!=typed[i-1]) return false; } else{ j++; } } if(j==name.size()) return true; else return false; } }; 上方为空间复杂度最低的题解: name和typed从零开始遍历,当name字符串走完,或者typed中当前字符和name当前字符不匹配的时候进行判断,如果两个字符串第一个字符就不匹配那必然false,如果不是i==0,那就判断这个字符是不是长按造成的,如果不是,也false;如果name和typed的当前字符相同,那么就说明name中的字符有匹配,j++。最后看j和name的长度是否相等,相等就说明name中全部字符都有匹配。(那么alex-alexss这种它能判断吗?能,因为for循环的范围是typed整个的长度,其中的字符只有name匹配和长按两种来源,不符合的直接return false了)。

----------------------------------------

class Solution { public: void table(string name,vector<pair<char,int>>& v1) { for(int i = 0; i < name.size();i++) { if(v1.empty()) { pair<char,int> p; p.first = name[i]; p.second = 1; v1.push_back(p); } else { if(v1.back().first == name[i]) v1.back().second++; else { pair<char,int> p; p.first = name[i]; p.second = 1; v1.push_back(p); } } } } bool isLongPressedName(string name, string typed) { vector<pair<char,int>> v1; vector<pair<char,int>> v2; table(name,v1); table(typed,v2); if(v1.size() != v2.size()) return false; for(int i = 0; i < v1.size();i++) { if(v1[i].first != v2[i].first) return false; else if(v1[i].second > v2[i].second) return false; } return true; } };

上方为空间复杂度最高的题解(看了几个答案,我还是不太明白这时空复杂度怎么定的,提交相同答案获得不同时空使用情况): 我试图理解这个答案的题解思路,首先把name和typed中每个不同字符连续出现的个数用table函数进行数目统计,在主要判断函数中,首先判断两个用于统计的vector长度是否一致,不一致直接退出;如果字符出现的顺序不同(这个想法是我一开始的想法,我当时觉得写出来会麻烦,事实证明确实要用我不熟悉的pair和vector,统计每个字符顺序出现的次数),那直接false;如果字符出现顺序相同,就判断连续字符个数是否相同,如果name中的字符数>typed中的,那就说明typed不符合要求,直接退出;其余情况都符合要求。分析应该是数据结构用的比较多,所以空间复杂度较大。

最新回复(0)