leetcode刷题,总结,记录,备忘 301

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 ( 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,表示在将前一个深度优先遍历结束之后才进行下一次的遍历,就是又套了一层进去。

可能说的不是太好,毕竟是个上个月写的东西了,,时间隔的有点久了,并且鄙人语文水平比较差,可能描述的不好,也只是提出自己的一个解决办法而已,,,说的不好勿喷。关键还是需要靠自己想出一个方法,然后在自己的思路上一步一步去深入解决这个问题,这是我做这道题的体会,因为一开始自己有点想法,虽然很多次都没提交过去,但是一直靠自己一点一点分析每个测试用例,最终通过,而没有直接去翻别人的东西,自己思考很重要,这是我做这道题得到的经验。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值