Leetcode 301 删除无效的括号

1.题目

在这里插入图片描述
思路:使用DFS+剪枝的方法解(因为要从左往右一个个判断,每次判断都会面临一些选择)
(1)首先计算出不符合配对要求的左右括号的个数
(2)每次递归都会遇到左括号、右括号、其他字符

  • 如果是左括号(你可以删除或者不删(等后面再删除,但是先得记着leftCount)
  • 如果是右括号,因为rightDeleted>0删除,或者不删,因为leftCount不为0,为了和左括号配对,添加右括号,否则return剪枝。
  • 如果是其他符号,直接添加。

(3)遍历完字符串,满足leftDeleted、rightDeleted、leftCount为0(不符合要求的左右括号必须删除,没有删除的左括号也得使用右括号类配对),这样才会生成符合要求的字符串。

2.解法

class Solution {
	  private HashSet<String> set = new HashSet<String>();
	  public List<String> removeInvalidParentheses(String s) {
		  // 集合中可以存放无重复的值
		  
		  ArrayList<String> arr = new ArrayList<String>();
		  int leftDeleted=0, rightDeleted=0;
		  for(int i=0; i < s.length(); i++) {
			  char ch = s.charAt(i);
			  if(ch == '(') {
				  leftDeleted++;
			  }else if(ch == ')') {
				  if (leftDeleted > 0) {
					  leftDeleted--;
				  }else {
					  rightDeleted++;
				  } 
			  }
		  }
		  dfs(s, 0, 0, leftDeleted, rightDeleted, new StringBuilder());
		  arr.addAll(set);
		  return arr;
	  }
	  private void dfs(String str, int index, int left, int leftDeleted, int rightDeleted, StringBuilder sb) {
		  if(index == str.length()) {
			  // 否合所有的条件
			  if(left == 0 && leftDeleted == 0 && rightDeleted == 0) {
				set.add(sb.toString());
				return;
			  }
		  } else {
			  char cur = str.charAt(index);
			  if(cur == '(') {
				    // 1.删除‘(’
				  if(leftDeleted > 0) {
					  StringBuilder newSb = new StringBuilder(sb);
					  dfs(str, index+1, left, leftDeleted-1, rightDeleted, newSb); 
				  }

                  // 2.不删除,删后面的‘(’
				  // 不使用同一StringBuilder
				  StringBuilder newSb = new StringBuilder(sb);
				  newSb.append(cur);
				  dfs(str, index+1, left+1, leftDeleted, rightDeleted, newSb);
				  
			  }else if(cur == ')') {
				  // 1.删除
				  if(rightDeleted > 0) {
					  StringBuilder newSb = new StringBuilder(sb);
					  dfs(str, index+1, left, leftDeleted, rightDeleted-1, newSb); 
				  }
                  
                  // 2.不删除的话,是因为有匹配的‘(’
				  if(left > 0) {
					  StringBuilder newSb = new StringBuilder(sb);
					  newSb.append(cur);
					  dfs(str, index+1, left-1, leftDeleted, rightDeleted, newSb); 
				  }else {
					// 如果没有左括号就结束,剪枝
					  return;
				  }
			  }else {
				  StringBuilder newSb = new StringBuilder(sb);
				  newSb.append(cur);
				  dfs(str, index+1, left, leftDeleted, rightDeleted, newSb); 
			  }
		    }  
	  	}
	  }

4.想法轨迹(不用看哈~~)

只考虑一个方案,而且这时候只有一个异常括号:
( 和 )的数量要匹配,所以当遇到( 的时候++count,遇到 )的时候 --count,但是要用pre保存异常的括号,最后要删除它。

public class DeadLockDemo {
	public void delete(String str) {
		int pre = 0;
		int count = 0;
		for(int i = 0; i < str.length(); i++) {
			if (str.charAt(i) != ')') {
				if(str.charAt(i) == '(') {
					++count;
					if(count >= 2) {
						pre = i;
					}	
				}
			} else {
				if(count > 0) {
					--count;
					if(count == 0) {
						pre = -1;
					}
				} else {
					pre = i;
				}	
			}
		}
		if (count == 0) {
			// 说明包含异常括号
			if(pre != -1) {
				// substring不包含最后一个元素
				String s = str.substring(0, pre) + str.substring(pre+1, str.length());
				System.out.println(s);
			}else {
				// 不包含异常括号
				System.out.println(str);
			}
			
		} else {
			System.out.println("");
		}	
	}
	
	public static void main(String[] args) {
		DeadLockDemo demo = new DeadLockDemo();
		demo.delete("(a)())()");
	}
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值