leetcode1021.删除最外层的括号

题目描述

有效括号字符串为空 """(" + A + ")" 或 A + B ,其中 A 和 B 都是有效的括号字符串,+ 代表字符串的连接。

  • 例如,"""()""(())()" 和 "(()(()))" 都是有效的括号字符串。

如果有效字符串 s 非空,且不存在将其拆分为 s = A + B 的方法,我们称其为原语(primitive),其中 A 和 B 都是非空有效括号字符串。

给出一个非空有效字符串 s,考虑将其进行原语化分解,使得:s = P_1 + P_2 + ... + P_k,其中 P_i 是有效括号字符串原语。

对 s 进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 s 。

示例 1:

输入:s = "(()())(())"
输出:"()()()"
解释:
输入字符串为 "(()())(())",原语化分解得到 "(()())" + "(())",
删除每个部分中的最外层括号后得到 "()()" + "()" = "()()()"。

示例 2:

输入:s = "(()())(())(()(()))"
输出:"()()()()(())"
解释:
输入字符串为 "(()())(())(()(()))",原语化分解得到 "(()())" + "(())" + "(()(()))",
删除每个部分中的最外层括号后得到 "()()" + "()" + "()(())" = "()()()()(())"。

示例 3:

输入:s = "()()"
输出:""
解释:
输入字符串为 "()()",原语化分解得到 "()" + "()",
删除每个部分中的最外层括号后得到 "" + "" = ""。

提示:

  • 1 <= s.length <= 105
  • s[i] 为 '(' 或 ')'
  • s 是一个有效括号字符串

知识储备

//假设栈内的数据类型是data

class data {

 int a;

 intb;

public:

 data(int x, int y):a(x), b(y) {}

};

data d(1,2);


emplace和push相同点

 1.直接传入对象(已构造好的对象)

S.push(d) 或 S.emplace(d);

 2.在传入时候构造对象

S.push(data(1,2));

S.emplce(data(1,2));

emplace和push不同点

 ·emplace可以直接传入构造对象需要的元素

S.emplace(1,2)

 解释:emplace传入构造对象所需要的元素,自动调用其构造函数生成对象,然后放在容器内(比如这里传入了1,2,它会自动调用一次data(1,2))

 而push,只能让其构造函数构造好了对象之后,使用拷贝构造函数,将拷贝后的对象放入容器

 相当于emplace直接把原料拿进家,自动用原料生成最终对象。而push生成实体后,再复制到自己家里,多了复制这一步。

 所以emplace相对于push,使用第三种方法会更节省内存。

注意:emplace_back(type) 对应 push_back(type)

 emplace(i, type) 对应于 insert(type, i)

 emplace_front(type) 对应于 push_front()

但是,对于stack 和 queue,只有push操作,所以也只有emplace操作,此时它们是相对应的。


题目中给出的字符串是由小括号"(",")"构成的。什么是有效的括号字符串呢?

空字符串""

左右完全匹配的括号,如"()","(())","(()())"。

哪些不是有效的括号字符串呢?

左右括号数不等的,如"(","(()","(((()"

左右顺序错了的,如")(","))("

题目中所谓的「原语」就是不能再拆分成两个有效括号字符串A+B的。

所有的「原语」,它的整体就是一个完整的括号匹配字符串,无法再一刀两断了。

而「非原语」,把它从某个部分切开以后,可以变成两个完全匹配的括号字符串。

解题方法

题目核心就是让我们实现一个括号匹配算法。

谈到括号匹配算法,就会想到「栈」。

本题的做法不难,核心就是:当栈为空的时候,说明已经形成了『原语』。

从左向右遍历字符串s

当遇到"("时,将其入栈;

当遇到")"时,说明匹配了前面最近一个"(",因此将栈顶弹出;

而结果字符串res,需要根据当前的"("或者")"是不是「原语」的开头和结束来决定。

当"("入栈前,栈是空,说明"("是『原语』的开头,因此不放入res中。

当遇到")"弹出栈顶以后,栈是空,说明")"是『原语』的结束,因此不放入res中。

C++代码
Classsolution{
Public:
stringremoveOuterParentheses(strings){
stringres;
stack<char>st;
for(autoc:s){
if(c==‘)’){
st.pop();
}
if(!st.empty()){
res.push_back(c);
}
if(c==‘(’){
st.emplace();
}
}
returnres;
}
};

  • 时间复杂度:O(n),n是输入s的长度,仅需遍历字符串一次

  • 空间复杂度:O(n)需要使用栈,栈深最大为n

注意if的顺序,三个不可以更换顺序,如果第三个在第二个之前会导致左侧
最外层的括号也被放入最终输出的字符串里,第二个在第一个之前会导致右
侧最外层括号也被放入最终输出的字符串中.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值