[每日一题] 102. 长按键入(字符串、双指针、样例踩坑题)

1. 题目来源

链接:长按键入
来源:LeetCode

2. 题目说明

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

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

说明:

初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。

示例1:

输入:name = “alex”, typed = “aaleex”
输出:true
解释:‘alex’ 中的 ‘a’ 和 ‘e’ 被长按。

示例2:

输入:name = “saeed”, typed = “ssaaedd”
输出:false
解释:‘e’ 一定需要被键入两次,但在 typed 的输出中不是这样。

示例3:

输入:name = “leelee”, typed = “lleeelee”
输出:true

扫描二维码关注公众号,回复: 8924375 查看本文章

示例4:

输入:name = “laiden”, typed = “laiden”
输出:true
解释:长按名字中的字符并不是必要的。

提示:

  1. name.length <= 1000
  2. typed.length <= 1000
  3. name 和 typed 的字符都是小写字母。

3. 题目解析

遍历name:
  1. 如果name中含有n个连续重复字母,双指针均向后移n位。
  2. 如果typed与name的当前字母相同,仅将typed指针向后移位,判断是否为该字母的长按情况。
  3. 在对name的一个字母进行遍历的时候,typed指针位置一定会发生改变,若没发生改变,则该位置字母不匹配name,故直接返回false,在此采用flag进行记录判断。
  4. 需要注意的是flag位置不能在情况1之前,应当在情况1、2中间,若样例为name = “saeed”,flag = "ssaaedd"会发生调用两次情况1的while,修改了j的大小,导致输出true。

这个写法简单易理解,但是坑太多,也是代码质量不行,也许在特殊的样例情况下仍然通不过,但在LeetCode上都能够提交成功了…无奈。


同理有遍历typed的双指针写法,感觉比遍历name的方法要好很多

遍历typed:
  1. 判断当前typed与当前name是否相同
  2. 如1不成立,判断与前一个name字符是否相同
  3. 如若2不成立返回false

由于两个string的有效字符长度会不同,需要判断

4. 代码展示

遍历name代码展示:

class Solution {
public:
    bool isLongPressedName(string name, string typed) {
        for (int i = 0, j = 0; i < name.length(); ++i) {
            while (name[i] == name[i + 1]) {
                ++i;
                ++j;
            }
            int flag = j;
            while (typed[j] == name[i]) {
                ++j;
            }

            if (flag == j) return false;
        }
        return true;
    }
};

以上代码遇到name = “aaall” typed = “daalll” 类似于这样的样例,name的重复元素会将typed覆盖掉连续的一部分。修改如下:

class Solution {
public:
    bool isLongPressedName(string name, string typed) {
        for (int i = 0, j = 0; i < name.length(); ++i) {  
            while ((name[i] == name[i + 1]) && (name[i] == typed[j])) {
                ++i;
                ++j;
            }
            int flag = j;
            while (typed[j] == name[i]) {
                ++j;
            }

            if (flag == j) return false;
        }
        return true;
    }
};

该flag位置必须在两while之间,若flag放置最前方,当name = “saeed”,flag = "ssaaedd"会发生调用两次情况1的while,修改了j的大小,导致输出true。
遍历typed代码展示:

bool isLongPressedName(string name, string typed) {
    int j = 0, len = name.size();
    for (int i = 0; i < typed.size(); i++) {
        if (typed[i] == name[j] && j < len) {
            j++;
            continue;
        }
        else if (j > 0 && typed[i] == name[j - 1]) //首字母不同时j-1超出索引范围
            continue;
        else
            return false;
    }
    if (j == len)
        return true;
    else
        return false;
}
发布了209 篇原创文章 · 获赞 42 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/yl_puyu/article/details/104046535