打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
​LeetCode刷题实战301: 删除无效的括号
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !

今天和大家聊的问题叫做 删除无效的括号,我们先来看题面:
https://leetcode-cn.com/problems/remove-invalid-parentheses/

Given a string s that contains parentheses and letters, remove the minimum number of invalid parentheses to make the input string valid.Return all the possible results. You may return the answer in any order.

给你一个由若干括号和字母组成的字符串 s ,删除最小数量的无效括号,使得输入的字符串有效。返回所有可能的结果。答案可以按 任意顺序 返回。

示例

示例 1

输入:s = "()())()"
输出:["(())()","()()()"]

示例 2

输入:s = "(a)())()"
输出:["(a())()","(a)()()"]

示例 3

输入:s = ")("
输出:[""]

解题

回溯法,剪枝的一点是如果当前是有括号的话,看前边左括号的数量,如果小于右括号的数量的话呢就没必要往下回溯了。

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Solution {

 private int len;
 private char[] charArray;
 private Set<String> validExpressions = new HashSet<>();

 public List<String> removeInvalidParentheses(String s) {
  this.len = s.length();
  this.charArray = s.toCharArray();

  // 第 1 步:遍历一次,计算多余的左右括号
  int leftRemove = 0;
  int rightRemove = 0;
  for (int i = 0; i < len; i++) {
   if (charArray[i] == '(') {
 leftRemove++;
   } else if (charArray[i] == ')') {
 // 遇到右括号的时候,须要根据已经存在的左括号数量决定
 if (leftRemove == 0) {
  rightRemove++;
 }
 if (leftRemove > 0) {
  // 关键:一个右括号出现可以抵销之前遇到的左括号
  leftRemove--;
 }
   }
  }

  // 第 2 步:回溯算法,尝试每一种可能的删除操作
  StringBuilder path = new StringBuilder();
  dfs(0, 0, 0, leftRemove, rightRemove, path);
  return new ArrayList<>(this.validExpressions);
 }

 /**
  * @param index 当前遍历到的下标
  * @param leftCount 已经遍历到的左括号的个数
  * @param rightCount 已经遍历到的右括号的个数
  * @param leftRemove 最少应该删除的左括号的个数
  * @param rightRemove 最少应该删除的右括号的个数
  * @param path 一个可能的结果
  */

 private void dfs(int index, int leftCount, int rightCount, int leftRemove, int rightRemove, StringBuilder path) {
  if (index == len) {
   if (leftRemove == 0 && rightRemove == 0) {
 validExpressions.add(path.toString());
   }
   return;
  }

  char character = charArray[index];
  // 可能的操作 1:删除当前遍历到的字符
  if (character == '(' && leftRemove > 0) {
   // 由于 leftRemove > 0,并且当前遇到的是左括号,因此可以尝试删除当前遇到的左括号
   dfs(index + 1, leftCount, rightCount, leftRemove - 1, rightRemove, path);
  }
  if (character == ')' && rightRemove > 0) {
   // 由于 rightRemove > 0,并且当前遇到的是右括号,因此可以尝试删除当前遇到的右括号
   dfs(index + 1, leftCount, rightCount, leftRemove, rightRemove - 1, path);
  }

  // 可能的操作 2:保留当前遍历到的字符
  path.append(character);
  if (character != '(' && character != ')') {
   // 如果不是括号,继续深度优先遍历
   dfs(index + 1, leftCount, rightCount, leftRemove, rightRemove, path);
  } else if (character == '(') {
   // 考虑左括号
   dfs(index + 1, leftCount + 1, rightCount, leftRemove, rightRemove, path);
  } else if (rightCount < leftCount) {
   // 考虑右括号
   dfs(index + 1, leftCount, rightCount + 1, leftRemove, rightRemove, path);
  }
  path.deleteCharAt(path.length() - 1);
 }
}


好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力 。

上期推文:
LeetCode1-300题汇总,希望对你有点帮助!

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
通过编码开关(旋转编码器)控制数码管的加减一|我爱单片机
Python|回溯算法解括号生成问题
[2020蓝桥杯B组省赛] E-七段码
dfs
LeetCode算法题-Average of Levels in Binary Tree(Java实现)
630,Leetcode原题电话号码的字母组合的两种解法,你会么?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服