0
点赞
收藏
分享

微信扫一扫

2023年5月3日 单调栈及其应用

星巢文化 2023-05-07 阅读 67

给你一个字符串 s ,请你判断它是否 有效 。字符串 s 有效 需要满足:假设开始有一个空字符串 t = "" ,你可以执行 任意次 下述操作将 t 转换为 s

  • 将字符串 "abc" 插入到 t 中的任意位置。形式上,t 变为 tleft + "abc" + tright,其中 t == tleft + tright 。注意,tlefttright 可能为

如果字符串 s 有效,则返回 true;否则,返回 false

示例 1:

Input: s = "aabcbc"
Output: true
Explanation:
"" -> "abc" -> "aabcbc"
Thus, "aabcbc" is valid.

示例 2:

Input: s = "abcabcababcc"
Output: true
Explanation:
"" -> "abc" -> "abcabc" -> "abcabcabc" -> "abcabcababcc"
Thus, "abcabcababcc" is valid.

示例 3:

Input: s = "abccba"
Output: false
Explanation: It is impossible to get "abccba" using the operation.

提示:

  • 1 <= s.length <= 2 * 10^4
  • s 由字母 'a''b''c' 组成

解法1 暴力

本题与20. 有效的括号类似,如果把问题改成「将字符串 (), [], {} 插入到 t t t 中的任意位置」,比如 () -> ([] -> ([]{}) ,根据「是否可用这种方式获得字符串 s s s 」来判断字符串有效,就完全一致了。

这里最简单的做法是逆向转换,不断从字符串中删除加入的 a b c abc abc 、最后删成空,就能返回 true

class Solution {
public:
    bool isValid(string s) {
        size_t pos;
        while ((pos = s.find("abc")) != string::npos)
            s.erase(pos, 3);
        return s.empty();
    }
};

解法2 栈

解法1复杂度高,于是想到了栈。20. 有效的括号也是用栈解决的:左括号入栈,对于右括号去判断栈顶是否为其匹配的左括号,匹配就让左括号出栈,否则返回 false 。本题也可用类似的方法完成:

  • 字符 a {a} a :类似左括号,直接入栈。
  • 字符 b {b} b如果栈为空,或者栈顶不为 a {a} a ,则返回 false ,否则将栈顶修改为 b {b} b(或者出栈再入栈)。
  • 字符 c {c} c如果栈为空,或者栈顶不为 b {b} b ,则返回 false ,否则弹出栈顶,相当于找到了一个 a b c {abc} abc
  • 代码实现时, b {b} b c {c} c 的逻辑可以合并在一起, a {a} a b {b} b 的入栈逻辑可以合并在一起。
  • 循环结束后,如果栈为空,则返回 true ,否则返回 false
class Solution {
public: 
	bool isValid(string s) { // s同时作为栈
		int i = 0; // i-1表示栈顶下标,i=0表示栈为空
		for (char c : s) {
			if (c > 'a' && (i == 0 || c - s[--i] != 1))
				return false;
			if (c < 'c') s[i++] = c; // 入栈
		}
		return i == 0;
	}
};

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n) ,其中 n n n s s s 的长度。
  • 空间复杂度: O ( n ) O(n) O(n) O ( 1 ) O(1) O(1) 。如果可以直接修改字符串(例如C++),那么只需 O ( 1 ) O(1) O(1) 的额外空间。
举报

相关推荐

0 条评论