7.13 两个括号匹配问题

两种问题,一个是括号的合法性,这种题目可以借助栈这种数据结构来解决

另一种是对于括号的生成,一般都要利用回溯递归的思想来解决;

括号生成

7.13 两个括号匹配问题_第1张图片

 分析 如果输入3,那么就是有六个位置,每个位置有两种情况,一共有2的六次方种,全部枚举出来,然后进行条件判断,剪枝优化。

括号生成的规则  1.一个合法的括号 左括号数量一定等于右括号数量 

2.对于一个合法的括号 任意子集,左括号的数量一定大于等于右括号的数量

回溯是一种用于解决组合优化问题的算法思想,它的核心思想是通过尝试不同的选择,逐步构建解空间,并在发现选择不可行时进行回退(撤销上一次的结果),以尝试其他可能的选择。

在括号生成问题中,我们需要生成符合条件的括号组合,即使在生成过程中出现了不符合条件的情况,我们也可以通过回溯来撤销上一次的结果,尝试其他可能的选择。

具体地说,回溯在每一步都有两种选择:添加一个左括号或添加一个右括号。我们通过递归调用回溯方法来尝试这两种选择,并根据当前的剩余左括号数和右括号数进行限制和判断。

如果在某一步选择添加左括号时,发现剩余的左括号数为0,或者右括号数小于左括号数(即当前的组合不符合括号的匹配规则),则需要进行回溯,撤销上一次的结果,尝试其他的选择。

同样地,如果在某一步选择添加右括号时,发现剩余的右括号数为0,或者右括号数小于左括号数,也需要进行回溯,撤销上一次的结果。

通过回溯,我们可以穷举所有可能的括号组合,并找到符合条件的组合。回溯的关键是在尝试选择后,通过撤销上一步的操作,进入下一步的选择。这样可以保证在遍历的过程中不会漏掉任何一个可能的解,同时也能够避免生成不符合条件的括号组合。

因此,回溯在解决括号生成问题中起到了关键的作用,能够有效地生成符合条件的括号组合。

代码

class Solution {
    List res = new ArrayList<>();

    public List generateParenthesis(int n) {
        StringBuilder track = new StringBuilder();
        //当n=3的时候,说明有6个位置,每个位置都有可能两种情况,一共是2的六次方总情况
        backTracking(n, n, track);
        // 需要找出符合题目要求的数量,
        return res;
    }

    void backTracking(int left, int right, StringBuilder t) {

        if (right < left) return;  //说明使用的右括号多余了左括号不可理
        // 数量小于 0 肯定是不合法的
        if (left < 0 || right < 0) return;

        if (left == 0 && right == 0) {
            res.add(t.toString());
            return;
        }


        t.append('(');//匹配左括号
        backTracking(left - 1, right, t);
        t.deleteCh arAt(t.length() - 1); //去掉这一个


        t.append(')');//匹配左括号
        backTracking(left, right - 1, t);
        t.deleteCharAt(t.length() - 1); //去掉这一个


    }
}

有效括号

用栈的思想来模拟,和机器人那道题思想一样的,将左边的括号加入到栈中去,遇到右边的括号进行匹配,求结果

class Solution {
    public boolean isValid(String s) {
        Deque deque = new LinkedList<>();
        char ch;
        for (int i = 0; i < s.length(); i++) {
            ch = s.charAt(i);
            //碰到左括号,就把相应的右括号入栈
            if (ch == '(') {
                deque.push(')');
            }else if (ch == '{') {
                deque.push('}');
            }else if (ch == '[') {
                deque.push(']');
            } else if (deque.isEmpty() || deque.peek() != ch) {
                return false;
            }else {//如果是右括号判断是否和栈顶元素匹配
                deque.pop();
            }
        }
        //最后判断栈中元素是否匹配
        return deque.isEmpty();
    }
}

以上的代码是一个用于检查括号是否匹配的解决方案。它使用堆栈(Deque)来实现匹配的检查。

解释上面代码片段的执行过程如下:

  1. 创建一个空的堆栈(Deque)deque ,用于存储右括号。
  2. 迭代字符串 s 中的每个字符:
    a. 将当前字符存储在变量 ch 中。
    b. 如果 ch 是左括号(‘(’,‘{’,‘[’),将其对应的右括号入栈。
    - 如果 ch 是 ‘(’,将 ‘)’ 入栈。
    - 如果 ch 是 ‘{’,将 ‘}’ 入栈。
    - 如果 ch 是 ‘[’,将 ‘]’ 入栈。
    c. 如果堆栈为空,或者栈顶元素与当前字符 ch 不相同,返回 false,表示括号不匹配。
    d. 如果是右括号,则与栈顶元素进行匹配:
    - 如果栈顶元素与当前字符 ch 相同,则将栈顶元素出栈。
    - 如果栈顶元素与当前字符 ch 不相同,返回 false,表示括号不匹配。
  3. 完成循环后,检查堆栈是否为空。如果堆栈为空,则表示所有的括号都有匹配的右括号;否则,返回 false
  4. 最终返回结果。

例如,对于输入字符串 “([])” ,代码的执行过程如下:

  1. 创建一个空的堆栈 deque
  2. 迭代字符串 “([])”:
    • 当前字符为 ‘(’,将 ‘)’ 入栈,栈中元素为 [‘)’]。
    • 当前字符为 ‘[’,将 ‘]’ 入栈,栈中元素为 [‘)’, ‘]’]。
    • 当前字符为 ‘]’,与栈顶元素匹配,栈顶元素 ‘]’ 出栈,栈中元素为 [‘)’]。
    • 当前字符为 ‘)’,与栈顶元素匹配,栈顶元素 ‘)’ 出栈,栈为空。
  3. 完成循环后,栈为空,返回 true,表示括号匹配。

因此,以上代码可以判断给定字符串中的括号是否匹配。如果匹配,返回 true,否则返回 false

你可能感兴趣的:(暑假算法集训,数据结构)