921. 使括号有效的最少添加——Leetcode(2022.10.4)【栈模拟】
文章目录
前言
假期摆烂摆的太舒服了,现在才开始更新。
题目描述
有兴趣的可以去试一下,个人觉得还是很简单的,如果对“栈”这个基础数据结构不熟悉的更应该练练手。
题目其实栈系列习题中的括号匹配题,主要点在于是我们对这个字符串添加括号达到使原来的无效的括号序列变为有效序列。
题目示例
输入:s = "())"
输出:1
输入:s = "((("
输出:3
提示
1 <= s.length <= 1000
s
只包含'('
和')'
字符。
本地调试输入输出
这个比较简单,为了不重复调用程序,我们可以将本地输入输出设置为多组测试,就是可以不断测试。
根据题目,输入只需使用题目给出的字符串,那么可以规定每个测试用例输入为一个有效字符串,即括号序列。
输出则直接输出需要增加括号的数量。
题解(栈模拟+空间优化)
我赌一根辣条,你看到这个题目的时候,一定会想到用栈来解决,是的,这道题目是让我们添加最少的括号实现有效,而根据题目有效的定义:其实就是让左右括号匹配,那我们可以用栈来存储左括号,遇到右括号的时候,如果栈不空,则出栈,否则此时则计数+1,遍历序列后,将计数值加上当前栈的元素数量即为最终需要添加的答案。
但是,这样做的问题在于,使用栈来存储会遇到极端情况的样例——序列全为左括号,这时空间复杂度即为:
O
(
n
)
O(n)
O(n),n
为序列的长度。
换个角度,我们一定需要用到括号序列来匹配嘛,其实我们只需要知道数量即可,我们最终需要的是栈内的左括号数量和待匹配的右括号数量之和,那简单,我们直接用两个变量来存储这两个数即可。
具体操作即为下述流程图所示:
算法复杂度 && 执行效率
设 n 为序列长度。
- 时间复杂度: O ( n ) O(n) O(n) 遍历了一遍序列。
- 空间复杂度: O ( 1 ) O(1) O(1) 使用了两个变量。
Leetcode执行效率:
Code(C++)
#include<bits/stdc++.h>
using namespace std;
class Solution
{
public:
// 栈模拟
// 我们可以用两个数值,分别记录非法左右括号的数量
// 结果即为二者的加和
// 注意非法左括号,遇到右括号的时候可以减少
int minAddToMakeValid(string s)
{
int left = 0, right = 0; // 记录非法(剩余)左右括号的数量
// 遍历字符串
for(char &ch : s)
{
// 如果出现左括号, 则数量+1
if(ch == '(')
{
++left;
}
// 否则需要判断此时有无多余的左括号,若有,则左-1
else if(left)
{
--left;
}
// 无则右+1
else
{
++right;
}
}
return left + right; // 返回需要增加的括号数量
}
};
int main()
{
Solution* sol = new Solution();
string s;
// 循环输入测试样例
while(cin >> s)
{
printf("%d\n", sol->minAddToMakeValid(s));
}
delete sol;
return 0;
}