<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ?LeetCode刷題實戰(zhàn)301: 刪除無效的括號

          共 7187字,需瀏覽 15分鐘

           ·

          2021-06-23 20:50

          算法的重要性,我就不多說了吧,想去大廠,就必須要經(jīng)過基礎(chǔ)知識和業(yè)務(wù)邏輯面試+算法面試。所以,為了提高大家的算法能力,這個公眾號后續(xù)每天帶大家做一道算法題,題目就從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 ,刪除最小數(shù)量的無效括號,使得輸入的字符串有效。返回所有可能的結(jié)果。答案可以按 任意順序 返回。


          示例


          示例 1

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

          示例 2

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

          示例 3

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


          解題


          回溯法,剪枝的一點是如果當前是有括號的話,看前邊左括號的數(shù)量,如果小于右括號的數(shù)量的話呢就沒必要往下回溯了。


          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] == ')') {
                          // 遇到右括號的時候,須要根據(jù)已經(jīng)存在的左括號數(shù)量決定
                          if (leftRemove == 0) {
                              rightRemove++;
                          }
                          if (leftRemove > 0) {
                              // 關(guān)鍵:一個右括號出現(xiàn)可以抵銷之前遇到的左括號
                              leftRemove--;
                          }
                      }
                  }

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

              /**
               * @param index 當前遍歷到的下標
               * @param leftCount 已經(jīng)遍歷到的左括號的個數(shù)
               * @param rightCount 已經(jīng)遍歷到的右括號的個數(shù)
               * @param leftRemove 最少應(yīng)該刪除的左括號的個數(shù)
               * @param rightRemove 最少應(yīng)該刪除的右括號的個數(shù)
               * @param path 一個可能的結(jié)果
               */

              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 != ')') {
                      // 如果不是括號,繼續(xù)深度優(yōu)先遍歷
                      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);
              }
          }


          好了,今天的文章就到這里,如果覺得有所收獲,請順手點個在看或者轉(zhuǎn)發(fā)吧,你們的支持是我最大的動力 。

          上期推文:
          LeetCode1-300題匯總,希望對你有點幫助!

          瀏覽 55
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  爱爱日韩一样 | 97色色免费视频 | 一级 a一级 a 免费观看免免黄 | 成人做爰黄AA片免费看三区 | 欧美成人一区三区无码乱码A片 |