题意:按case理解
示例 1:
输入:"(()())(())"
输出:"()()()"
解释:
输入字符串为 "(()())(())",原语化分解得到 "(()())" + "(())",
删除每个部分中的最外层括号后得到 "()()" + "()" = "()()()"。
示例 2:
输入:"(()())(())(()(()))"
输出:"()()()()(())"
解释:
输入字符串为 "(()())(())(()(()))",原语化分解得到 "(()())" + "(())" + "(()(()))",
删除每个部分中的最外层括号后得到 "()()" + "()" + "()(())" = "()()()()(())"。
示例 3:
输入:"()()"
输出:""
解释:
输入字符串为 "()()",原语化分解得到 "()" + "()",
删除每个部分中的最外层括号后得到 "" + "" = ""。
S.length <= 10000
S[i]
为"("
或")"
S
是一个有效括号字符串
初步思路
和数据结构中,检查是否是个有效括号串/括号是否匹配应该是类似方法,都是用栈
检查是否为合法串的思路是:遍历:(1)遇左括号,无论是花括号,还是中括号,小括号,入栈
(2)遇右括号,检查栈首:如果栈首为相匹配的左括号,弹出,扫描下一个字符;如果遇到不匹配 / 非左括号 / 栈空,报错
(3)扫描完全串,栈空:匹配,否则:报错
看到本题的初步想法
输出串初始为空,关键在每次扫描到右括号,并且栈里除了一个左括号啥都没有了的时候,直接出栈,并跳走。否则:如果是左括号,进栈,接到输出串,如果是右括号,先出栈,再接到输出串。最后输出输出串。(刚开始以为是在扫到栈空的时候,后来改成了栈内只有一个左括号了的时候了)
(不行,弹出一定是()()一对一对的形式,不是输入串的形式)
正确思路
遇到什么加什么,除了遇到最外层括号的情况不加(如何控制这种情况不加呢,就是加一个标记tag)
最终AC的c++代码
class Solution {
public:
string removeOuterParentheses(string str) {
stack<char>s;
string outstr="";
bool tag = true;
for(int i=0; i<str.length();i++)
{
if(str[i]=='(')
{
s.push('(');
if( tag )
tag = false;
else
outstr.push_back('(');
}
else
{
s.pop();
if( s.empty() )
tag=true;
else
outstr.push_back(')');
}
}
return outstr;
}
};
写代码中学到的新东西
1 用stl写栈的命令:
(1)头文件:#include<stack>
(2)要在main外定义一个栈:stack<char> s; 注意<>和s之间的空格!;
(3)入栈:s.push(ch);出栈:s.pop();
注意!C++中stack:
pop(), 返回void,不返回弹出的栈顶元素
top(),返回栈顶的引用。
所以想要提取栈顶元素,直接用s.top();
stack是一种“先进后出(FILO)”数据结构。不允许被遍历,没有迭代器(这个是对的吗??)
只有一种方法遍历:while( !s.empty() ) { cout << s.top() << endl; s.pop(); }
(4)栈长:s.size();栈首:k=s.top();
(5)栈空:s.empty() ;
2 c++中string的操作
(1)初始化一个空串:string s = “”;
(2)在string串后加入一个字符(就加一个字符):s.push_back(ch);
在整个string串前插入一个字符:s.pop_back(ch);
(3)一个字符一个字符地遍历string串:for(int i=0; i<str.length();i++)
(4)append可用于一个串后面接另一个串 / 后面加几个重复字符
要记得手动模拟一遍案例,把题目理解好,别急
总结
(1)对称美~~~代码优美的话思路应该不会错,代码很丑得重新想思路,思路可能不清晰了,哈哈哈哈。
(2)思路需要反复修正,慢慢理清思路,或者先理清思路再写代码,不要着急
(3)遇到这种括号相关的问题,左括号一般用来进栈,右括号灵活处理