[前端]_一起刷leetcode 844. 比较含退格的字符串

293 阅读3分钟

大家好,我是挨打的阿木木,爱好算法的前端摸鱼老。最近会频繁给大家分享我刷算法题过程中的思路和心得。如果你也是想提高逼格的摸鱼老,欢迎关注我,一起学习。

题目

844. 比较含退格的字符串

给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,请你判断二者是否相等。# 代表退格字符。

如果相等,返回 true ;否则,返回 false 。

注意: 如果对空文本输入退格字符,文本继续为空。

 

示例 1:

输入: s = "ab#c", t = "ad#c"
输出: true
解释: S 和 T 都会变成 “ac”。

示例 2:

输入: s = "ab##", t = "c#d#"
输出: true
解释: s 和 t 都会变成 “”。

示例 3:

输入: s = "a##c", t = "#a#c"
输出: true
解释: s 和 t 都会变成 “c”。

示例 4:

输入: s = "a#c", t = "b"
输出: false
解释: s 会变成 “c”,但 t 仍然是 “b”。

 

提示:

  • 1 <= s.length, t.length <= 200
  • s 和 t 只含有小写字母以及字符 '#'

 

进阶:

  • 你可以用 O(N) 的时间复杂度和 O(1) 的空间复杂度解决该问题吗?

思路

  1. 用栈的思想,每次往当前栈stack中推入当前字符,遇到#就从栈中删除掉最后一位元素;
  2. 分别格式化st, 比较它们格式化后的结果是否一样;
  3. 由于格式化的方法是一模一样的,所以我们抽离成一个公共方法,减少冗余代码。

实现

/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var backspaceCompare = function(s, t) {
    return formatString(s) === formatString(t);
};

function formatString(str) {
    // 先遍历s字符串,遇到"#"删除一个元素
    let stack = [];

    const n = str.length;
    for (let i = 0; i < n; i++) {
        if (str[i] === "#") {
            stack.pop();
        } else {
             stack.push(str[i]);
        }
    }

    // 返回格式化后的字符串
    return stack.join("");
}

结果

image.png

结果一般般,这显然达不到我们刷题的目的。刷题至少保证时间复杂度到80%以上,最好能在90%。而且题目也说了,进阶要求我们使用空间复杂度O(1), 说明这道题有其他的解法。

优化

这就又回到了找规律的过程了,其实说难也不难,稍微想想,匹配两个字符串,除了用栈我第一个想到的是指针,可是如果从前往后遍历,咱们不知道前面的元素要不要保留。那么不妨换个角度,从后往前遍历,遇到#了就记录一下当前有几个需要删除的元素,而且从后面开始如果遇到不匹配的就可以直接返回false了。

优化代码

/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
function backspaceCompare(s, t) {
    let n = s.length - 1, m = t.length - 1;

    // 从倒数第一位一直遍历到第一位
    while (n >= 0 && m >= 0) {
        // 执行删除,如果有需要的话
        n = getFirstChart(s, n);
        m = getFirstChart(t, m);

        // 开始配对
        if (s[n] !== t[m]) {
            return false;
        }

        // 抬走,下一位
        n--;
        m--;
    }

    // 看看是否同时为 0, 可能残留了"a#", 所以执行多一次删除看看
    return n === m || getFirstChart(s, n) === getFirstChart(t, m);
};

// 找到第一个有效的字符
function getFirstChart(str, len) {
  // 记录有多少个待删除元素
  let count = 0;

  // 遇到删除符号就往前删
  // && len > -1 的意思是:如果第一个元素都删掉了,直接返回
  while ((str[len] === "#" || count > 0) && len > -1) {
    count = str[len] === "#" ? count + 1 : count - 1;
    len--;
  }

  return len;
}

优化结果

image.png 看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。