前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【算法题解】 Day15 栈

【算法题解】 Day15 栈

作者头像
sidiot
发布2023-08-26 19:33:22
1270
发布2023-08-26 19:33:22
举报
文章被收录于专栏:技术大杂烩技术大杂烩
持续创作,加速成

844. 比较含退格的字符串

题目

844. 比较含退格的字符串 难度:easy

给定?s?和?t?两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回?true?。#?代表退格字符。

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

示例 1:

代码语言:javascript
复制
输入: s = "ab#c", t = "ad#c"
输出: true
解释: s 和 t 都会变成 "ac"。

示例 2:

代码语言:javascript
复制
输入: s = "ab##", t = "c#d#"
输出: true
解释: s 和 t 都会变成 ""。

示例 3:

代码语言:javascript
复制
输入: s = "a#c", t = "b"
输出: false
解释: s 会变成 "c",但 t 仍然是 "b"。

提示:

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

&nbsp;

方法一:模拟

思路

模拟这一个过程,还原给定字符串的一般形式。然后直接比较两字符串是否相等即可。

具体地,我们用栈处理遍历过程,每次我们遍历到一个字符:

  • 如果它是退格符,那么我们将栈顶弹出;
  • 如果它是普通字符,那么我们将其压入栈中。
代码语言:javascript
复制
for ch in s:
    if ch != "#":
        append(ch)
    else:
        pop()

&nbsp;

解题

Python:

代码语言:javascript
复制
class Solution:
    def backspaceCompare(self, S: str, T: str) -> bool:
        def build(s: str) -> str:
            ret = list()
            for ch in s:
                if ch != "#":
                    ret.append(ch)
                elif ret:
                    ret.pop()
            return "".join(ret)
        
        return build(S) == build(T)

Java:

代码语言:javascript
复制
class Solution {
    public boolean backspaceCompare(String S, String T) {
        return build(S).equals(build(T));
    }

    public String build(String str) {
        StringBuffer ret = new StringBuffer();
        int length = str.length();
        for (int i = 0; i < length; ++i) {
            char ch = str.charAt(i);
            if (ch != '#') {
                ret.append(ch);
            } else {
                if (ret.length() > 0) {
                    ret.deleteCharAt(ret.length() - 1);
                }
            }
        }
        return ret.toString();
    }
}

&nbsp;

方法二:双指针

思路

一个字符是否会被删掉,只取决于该字符后面的退格符,而与该字符前面的退格符无关。因此当我们逆序地遍历字符串,就可以立即确定当前字符是否会被删掉。

具体地,我们定义 skip 表示当前待删除的字符的数量。每次我们遍历到一个字符:

  • 若该字符为退格符,则我们需要多删除一个普通字符,我们让?skip?加?1;
  • 若该字符为普通字符:
    • 若?skip?为?0,则说明当前字符不需要删去;
    • 若?skip?不为?0,则说明当前字符需要删去,我们让?skip?减?1。

这样,我们定义两个指针,分别指向两字符串的末尾。每次我们让两指针逆序地遍历两字符串,直到两字符串能够各自确定一个字符,然后将这两个字符进行比较。重复这一过程直到找到的两个字符不相等,或遍历完字符串为止。

1.gif
1.gif

&nbsp;

解题

Python:

代码语言:javascript
复制
class Solution:
    def backspaceCompare(self, S: str, T: str) -> bool:
        i, j = len(S) - 1, len(T) - 1
        skipS = skipT = 0

        while i >= 0 or j >= 0:
            while i >= 0:
                if S[i] == "#":
                    skipS += 1
                    i -= 1
                elif skipS > 0:
                    skipS -= 1
                    i -= 1
                else:
                    break
            while j >= 0:
                if T[j] == "#":
                    skipT += 1
                    j -= 1
                elif skipT > 0:
                    skipT -= 1
                    j -= 1
                else:
                    break
            if i >= 0 and j >= 0:
                if S[i] != T[j]:
                    return False
            elif i >= 0 or j >= 0:
                return False
            i -= 1
            j -= 1
        
        return True

Java:

代码语言:javascript
复制
class Solution {
    public boolean backspaceCompare(String S, String T) {
        int i = S.length() - 1, j = T.length() - 1;
        int skipS = 0, skipT = 0;

        while (i >= 0 || j >= 0) {
            while (i >= 0) {
                if (S.charAt(i) == '#') {
                    skipS++;
                    i--;
                } else if (skipS > 0) {
                    skipS--;
                    i--;
                } else {
                    break;
                }
            }
            while (j >= 0) {
                if (T.charAt(j) == '#') {
                    skipT++;
                    j--;
                } else if (skipT > 0) {
                    skipT--;
                    j--;
                } else {
                    break;
                }
            }
            if (i >= 0 &amp;&amp; j >= 0) {
                if (S.charAt(i) != T.charAt(j)) {
                    return false;
                }
            } else {
                if (i >= 0 || j >= 0) {
                    return false;
                }
            }
            i--;
            j--;
        }
        return true;
    }
}

&nbsp;

394. 字符串解码

题目

394. 字符串解码 难度:medium

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为:?k[encoded_string],表示其中方括号内部的?encoded_string?正好重复?k?次。注意?k?保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数?k?,例如不会出现像?3a?或?2[4]?的输入。

示例 1:

代码语言:javascript
复制
输入: s = "3[a]2[bc]"
输出: "aaabcbc"

示例 2:

代码语言:javascript
复制
输入: s = "3[a2[c]]"
输出: "accaccacc"

示例 3:

代码语言:javascript
复制
输入: s = "2[abc]3[cd]ef"
输出: "abcabccdcdcdef"

示例 4:

代码语言:javascript
复制
输入: s = "abc3[cd]xyz"
输出: "abccdcdcdxyz"

提示:

  • 1 <= s.length <= 30
  • s?由小写英文字母、数字和方括号?'[]'?组成
  • s?保证是一个?有效?的输入。
  • s?中所有整数的取值范围为?[1, 300] &nbsp;

方法一:栈

思路

本题中可能出现括号嵌套的情况,比如?2[a2[bc]],这种情况下我们可以先转化成?2[abcbc],在转化成abcbcabcbc。我们可以把字母、数字和括号看成是独立的 TOKEN,并用栈来维护这些 TOKEN。具体的做法是,遍历这个栈:

  • 如果当前的字符为数位,解析出一个数字(连续的多个数位)并进栈
  • 如果当前的字符为字母或者左括号,直接进栈 如果当前的字符为右括号,开始出栈,一直到左括号出栈,出栈序列反转后拼接成一个字符串,此时取出栈顶的数字(此时栈顶一定是数字,想想为什么? ),就是这个字符串应该出现的次数,我们根据这个次数和字符串构造出新的字符串并进栈

重复如上操作,最终将栈中的元素按照从栈底到栈顶的顺序拼接起来,就得到了答案。注意:这里可以用不定长数组来模拟栈操作,方便从栈底向栈顶遍历。 &nbsp;

解题

Java:

代码语言:javascript
复制
class Solution {
    int ptr;

    public String decodeString(String s) {
        LinkedList<String> stk = new LinkedList<String>();
        ptr = 0;

        while (ptr < s.length()) {
            char cur = s.charAt(ptr);
            if (Character.isDigit(cur)) {
                // 获取一个数字并进栈
                String digits = getDigits(s);
                stk.addLast(digits);
            } else if (Character.isLetter(cur) || cur == '[') {
                // 获取一个字母并进栈
                stk.addLast(String.valueOf(s.charAt(ptr++))); 
            } else {
                ++ptr;
                LinkedList<String> sub = new LinkedList<String>();
                while (!"[".equals(stk.peekLast())) {
                    sub.addLast(stk.removeLast());
                }
                Collections.reverse(sub);
                // 左括号出栈
                stk.removeLast();
                // 此时栈顶为当前 sub 对应的字符串应该出现的次数
                int repTime = Integer.parseInt(stk.removeLast());
                StringBuffer t = new StringBuffer();
                String o = getString(sub);
                // 构造字符串
                while (repTime-- > 0) {
                    t.append(o);
                }
                // 将构造好的字符串入栈
                stk.addLast(t.toString());
            }
        }

        return getString(stk);
    }

    public String getDigits(String s) {
        StringBuffer ret = new StringBuffer();
        while (Character.isDigit(s.charAt(ptr))) {
            ret.append(s.charAt(ptr++));
        }
        return ret.toString();
    }

    public String getString(LinkedList<String> v) {
        StringBuffer ret = new StringBuffer();
        for (String s : v) {
            ret.append(s);
        }
        return ret.toString();
    }
}

&nbsp;

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-10-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 844. 比较含退格的字符串
    • 题目
      • 方法一:模拟
        • 思路
        • 解题
      • 方法二:双指针
        • 思路
        • 解题
    • 394. 字符串解码
      • 题目
        • 方法一:栈
          • 思路
          • 解题
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
      http://www.vxiaotou.com