leetcode刷题,总结,记录,备忘 301
2016-05-02 20:23
351 查看
leetcode301Remove Invalid Parentheses
Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results.
Note: The input string may contain letters other than the parentheses
Examples:
Credits:
Special thanks to @hpplayer for adding this problem and creating all test cases.
Subscribe to see which companies asked this question
这是一道hard题,真的很难,我上个月刚解决他,一直没来得及写在博客中,今天就来好好分析下。虽然这个题目的通过率是百分之30,但是我一共提交20多次才通过,因为有些测试用例比较特殊,所以一直对自己算法改来改去。首先先把代码整体放上来,再仔细分析。
接着是对已经处理过的字符串的一个遍历工作,声明一个int变量,用来记录这个字符串中,到底出现过多少次'('和')',最后通过flag是正还是负来判断这个字符串中是'('多还是')'多。遍历完字符串之后的部分是重点部分,也是整个算法的关键。有3种情况,flag等于0,flag大于0,flag小于0,我必须说的是,flag大于0的情况是最容易的,所以我们先搁置,看下其他2种情况。
flag小于0的时候,表示字符串中')'的个数过多,需要删除多余的')',但是有一种情况比如"()))))(()",这样的结果flag会等于-3,那我们就以为是多了3个')',直接使用深度优先算法,对字符串中的各种3个')'的组合删掉就行了。理论上是如此,但是实际上,由于在字符串后面的部分,出现了"(()"这样的情况,所以如果单纯的进行以')'为目标的删除,结果不是正确的,可能会有这样的结果"())(()",必然是错误的,所以如果对于flag<0的情况,首先在上一层进行遍历字符串的时候,必须记录下出现')'最大值时下标索引,然后在后续过程中以该索引为起点,计算是否有过多的'('出现,记录下数值为deepoop,再次之后调用深度优先的函数,2个深度参数分别为abs(flag)
+ abs(deepopp)和abs(deepopp),分别表示')'和'('需要删除的个数,在深度优先函数中进行分别删除,最终得到的结果才是正确的,使用深度优先剔除字符的函数我们后面再说。
flag==0的时候,此时并不能以为这个字符串就是正确的了,比如"())(()"这样虽然flag=0,但是并不是正确的。所以我们需要从之前遍历字符串时得到的出现最大次数')'的下标索引,以这个为起始点,进行遍历,其实是可以找到多出的'('的个数,然后相应的')'的个数即abs(flag)需要加上这样的个数,然后在深度优先函数中对其进行剔除。
flag>0的情况就比较简单了,只需得到'('出现最多的次数值即可。
之后来说说深度优先计算剔除字符的函数,无非是使用了2个deep,先将一个字符全部删掉后,再进行另一个字符的删除,有2个判断条件,deep == 0和deepopp == 0,表示在将前一个深度优先遍历结束之后才进行下一次的遍历,就是又套了一层进去。
可能说的不是太好,毕竟是个上个月写的东西了,,时间隔的有点久了,并且鄙人语文水平比较差,可能描述的不好,也只是提出自己的一个解决办法而已,,,说的不好勿喷。关键还是需要靠自己想出一个方法,然后在自己的思路上一步一步去深入解决这个问题,这是我做这道题的体会,因为一开始自己有点想法,虽然很多次都没提交过去,但是一直靠自己一点一点分析每个测试用例,最终通过,而没有直接去翻别人的东西,自己思考很重要,这是我做这道题得到的经验。
Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results.
Note: The input string may contain letters other than the parentheses
(and
).
Examples:
"()())()" -> ["()()()", "(())()"] "(a)())()" -> ["(a)()()", "(a())()"] ")(" -> [""]
Credits:
Special thanks to @hpplayer for adding this problem and creating all test cases.
Subscribe to see which companies asked this question
这是一道hard题,真的很难,我上个月刚解决他,一直没来得及写在博客中,今天就来好好分析下。虽然这个题目的通过率是百分之30,但是我一共提交20多次才通过,因为有些测试用例比较特殊,所以一直对自己算法改来改去。首先先把代码整体放上来,再仔细分析。
class Solution { public: vector<string> vs; vector<int> itemp; string head; string tail; void function(string s, int start, int startopp, int deep, int deepopp, char tar, char opp) { if (deep == 0) { if (deepopp == 0) { int flag = 0; for (int i = 0; i < s.size(); ++i) { if (s[i] == '(') { flag++; } else if (s[i] == ')') { flag--; } if (flag < 0) { return; } } vs.push_back(head + s + tail); return; } for (int i = startopp; i < s.size(); ++i) { if(s[i] == opp) { string temp = s; temp.erase(i, 1); function(temp, i, startopp, deep, deepopp - 1, tar, opp); } } } for (int i = start; i < s.size(); ++i) { if(s[i] == tar) { string temp = s; temp.erase(i, 1); function(temp, i, startopp, deep - 1, deepopp, tar, opp); } } } vector<string> removeInvalidParentheses(string s) { if (s.size() == 0) { vs.push_back(""); return vs; } while (s.size() != 0 && (s[0] == ')' || s[s.size() - 1] == '(' || isalpha(s[0]) || isalpha(s[s.size() - 1]))) { if (s[0] == ')') { s.erase(0, 1); continue; } if (s[s.size() - 1] == '(') { s.erase(s.size() - 1, 1); continue; } if (isalpha(s[0])) { head = head + s[0]; s.erase(0, 1); continue; } if (isalpha(s[s.size() - 1])) { tail = s[s.size() - 1] + tail; s.erase(s.size() - 1, 1); continue; } } int flag = 0; char target; char opp; int min_right = 0; int max_left = 0; int deepopp = 0; int index_right = -1; for (int i = 0; i < s.size(); ++i) { if (s[i] == '(') { flag++; } else if (s[i] == ')') { flag--; } if (flag > max_left) { max_left = flag; } if (flag < min_right) { min_right = flag; index_right = i; } } if (flag == 0) { int f = 0; for (int i = index_right + 1; i < s.size(); ++i) { if (s[i] == '(') { f++; } else if (s[i] == ')') { f--; } } if (f > 0) { deepopp = f; } else { deepopp = 0; } if (deepopp == 0) { s = head + s + tail; vs.push_back(s); return vs; } else { target = '('; opp = ')'; } } else if (flag > 0) { target = '('; opp = ')'; deepopp = min_right; } else if (flag < 0) { target = ')'; opp = '('; int f = 0; for (int i = index_right + 1; i < s.size(); ++i) { if (s[i] == '(') { f++; } else if (s[i] == ')') { f--; } } if (f > 0) { deepopp = f; } else { deepopp = 0; } } function(s, 0, 0, abs(flag) + abs(deepopp), abs(deepopp), target, opp); set<string> set_s(vs.begin(), vs.end()); vector<string> res(set_s.begin(), set_s.end()); return res; } };算法的一开始,首先我们需要剔除一些可能的输入字符串的情况,保证我们开始处理的字符串是由'('开头,由')'结尾的,如果左边的开头是')'或者右边的结尾是'('就直接先删除掉,不用管,如果开头和结尾是字母的话,就分别删除掉,然后保存在单独的2个字符串中,在最终的结果中分别在头尾部分添加上去,一直进行这样的循环,直到符合我们的条件由'('开头,由')'结尾,然后进行下一步工作。
接着是对已经处理过的字符串的一个遍历工作,声明一个int变量,用来记录这个字符串中,到底出现过多少次'('和')',最后通过flag是正还是负来判断这个字符串中是'('多还是')'多。遍历完字符串之后的部分是重点部分,也是整个算法的关键。有3种情况,flag等于0,flag大于0,flag小于0,我必须说的是,flag大于0的情况是最容易的,所以我们先搁置,看下其他2种情况。
flag小于0的时候,表示字符串中')'的个数过多,需要删除多余的')',但是有一种情况比如"()))))(()",这样的结果flag会等于-3,那我们就以为是多了3个')',直接使用深度优先算法,对字符串中的各种3个')'的组合删掉就行了。理论上是如此,但是实际上,由于在字符串后面的部分,出现了"(()"这样的情况,所以如果单纯的进行以')'为目标的删除,结果不是正确的,可能会有这样的结果"())(()",必然是错误的,所以如果对于flag<0的情况,首先在上一层进行遍历字符串的时候,必须记录下出现')'最大值时下标索引,然后在后续过程中以该索引为起点,计算是否有过多的'('出现,记录下数值为deepoop,再次之后调用深度优先的函数,2个深度参数分别为abs(flag)
+ abs(deepopp)和abs(deepopp),分别表示')'和'('需要删除的个数,在深度优先函数中进行分别删除,最终得到的结果才是正确的,使用深度优先剔除字符的函数我们后面再说。
flag==0的时候,此时并不能以为这个字符串就是正确的了,比如"())(()"这样虽然flag=0,但是并不是正确的。所以我们需要从之前遍历字符串时得到的出现最大次数')'的下标索引,以这个为起始点,进行遍历,其实是可以找到多出的'('的个数,然后相应的')'的个数即abs(flag)需要加上这样的个数,然后在深度优先函数中对其进行剔除。
flag>0的情况就比较简单了,只需得到'('出现最多的次数值即可。
之后来说说深度优先计算剔除字符的函数,无非是使用了2个deep,先将一个字符全部删掉后,再进行另一个字符的删除,有2个判断条件,deep == 0和deepopp == 0,表示在将前一个深度优先遍历结束之后才进行下一次的遍历,就是又套了一层进去。
可能说的不是太好,毕竟是个上个月写的东西了,,时间隔的有点久了,并且鄙人语文水平比较差,可能描述的不好,也只是提出自己的一个解决办法而已,,,说的不好勿喷。关键还是需要靠自己想出一个方法,然后在自己的思路上一步一步去深入解决这个问题,这是我做这道题的体会,因为一开始自己有点想法,虽然很多次都没提交过去,但是一直靠自己一点一点分析每个测试用例,最终通过,而没有直接去翻别人的东西,自己思考很重要,这是我做这道题得到的经验。
相关文章推荐
- android常用控件
- java.net.NoRouteToHostException: No route to host
- hdu 5441 Travel(带权并查集)
- 从语言与二进制之间的关系
- yugong-mysql查看表字段和主键约束
- Codeforces Beta Round #11 A. Increasing Sequence
- eclipse恢复已删除的文件
- HDU 1326 Box of Bricks(水题)
- Android:通过build gradle中的buildTypes设置自动log开关(一)
- 平衡二叉树旋转原理(图示)
- 4568: [Scoi2016]幸运数字 倍增+线性基
- 输入的处理1;
- 设计模式——适配器模式
- java的常用的dos命令
- 不同进制间的相互转换的理解
- netty in action sixth chapter summarize
- ansible之cron模块
- Laxcus大数据管理系统2.0(13)- 总结
- Laxcus大数据管理系统2.0(12)- 第十章 运行
- Laxcus大数据管理系统2.0(11)- 第九章 容错