Parentheses problems

Contents

Parentheses problems

LeetCode : 20. Valid Parentheses

LeetCode Difficulty
20. Valid Parentheses Easy
921. Minimum Add to Make Parentheses Valid Medium
1541. Minimum Insertions to Balance a Parentheses String Medium

1. Valid Parentheses 单一括号

input : ()))((
如果只有一种括号,如何判断是否合法?

每个右括号的左边必须有一个左括号

/**
* 一个字符串合法括号字符串的条件:
* 1. 左右括号数量相等;
* 2. 任意一个位置左括号的数量都大于等于右括号的数量。
*/

/**
 * 定义一个函数,检验字符串是否为合法括号字符串
 * @param str 待检验的字符串
 * @return boolean 类型,是/否合法括号字符串
 */
boolean isValid(String str) {
    // 待匹配的左括号数量
    int left = 0;
    for (int i = 0; i < str.length(); i++) {
        if (str.charAt(i) == '(') {
            left++;
        } else {
            // 遇到右括号
            left--;
        }

        // 右括号太多
        if (left == -1)
            return false;
    }
    // 是否所有的左括号都被匹配了
    return left == 0;
}

2. Leetcode #20 Valid Parentheses 多种括号

思路:什么情况下会判定为 unvalid?
1. 前边为空,直接遇到闭括号} } ]
2. 前边已经有开括号,但是新遇到的闭括号不能匹配

解法:
遇到左括号就入栈,遇到右括号就去栈中寻找最近的左括号,看是否匹配
1. 判断corner case 输入为空或者长度为0 (题目已给范围 可忽略此步)
2. 用stack来做
    1) 当遇到开括号时:入栈
    2) 遇到闭括号时:
        1 栈是否为空? false
        2 括号是否可以匹配上? stack.pop() : false
class Solution {
    public boolean isValid(String s) {
        if (s == null || s.length() == 0) return false;
        Deque<Character> stack = new ArrayDeque<>();
        for (int i = 0; i < s.length(); i++) {
            // 1) 当遇到开括号时:入栈
            if (s.charAt(i) == '(' || s.charAt(i) == '{' || s.charAt(i) == '[') {
                stack.offerLast(s.charAt(i));
            } else  {
                // 遇到闭括号时:
                // 1 栈是否为空? false. 2 括号是否可以匹配上? stack.pop() : false
                if (stack.isEmpty() || stack.peekLast() != leftOf(s.charAt(i))) return false;
                else stack.pollLast();
            }
        }
        return stack.isEmpty();
    }
    private char leftOf(char i) {
        if (i == ')') return '(';
        if (i == '}') return '{';
        return '[';
    }
}

3. Leetcode 921. Minimum Add to Make Parentheses Valid

思考:只有一种括号
1. 左边没有开括号,遇到闭括号 - 需要添加左括号
2. 只剩下左括号 - 添加右括号

解法:
以开括号为基准 res记录插入左括号次数,通过维护对闭括号的需求数 need,来计算最小的插入次数

1. 当need == -1时:闭括号太多,左边没有开括号

    因为只有遇到右括号 ) 的时候才会 need--,need == -1 意味着右括号太多了,所以需要插入左括号。

    比如说 s = "))" 这种情况,需要插入 2 个左括号,使得 s 变成 "()()",才是一个有效括号串。

2. 返回res+need

    因为 res 记录的左括号的插入次数,need 记录了右括号的需求,当 for 循环结束后,若 need 不为 0,那么就意味着右括号还不够,需要插入。

    比如说 s = "))(" 这种情况,插入 2 个左括号之后,还要再插入 1 个右括号,使得 s 变成 "()()()",才是一个有效括号串。
/**
 * 给定一个由 '(' 和 ')' 括号组成的字符串 S,我们需要添加最少的括号( '(' 或是 ')',可以在任何位置),以使得到的括号字符串有效。
 * 在完成此题时,保证输入始终是有效的。
 *
 * 示例:
 * 输入:"())"
 * 输出:1
 */
public int minAddToMakeValid(String S) {
    // 记录插入次数
    int res = 0;
    // 变量记录右括号的需求量
    int need = 0;

    for (int i = 0; i < S.length(); i++) {
        if (S.charAt(i) == '(') {
            // 对右括号的需求 + 1
            need++;
        }

        if (S.charAt(i) == ')') {
            // 对右括号的需求 - 1
            need--;

            if (need == -1) {
                need = 0;
                // 需插入一个左括号
                res++;
            }
        }
    }

    // 插入剩余所需的右括号
    return res + need;
}

4. Leetcode 1541. Minimum Insertions to Balance a Parentheses String

核心思路还是和刚才一样,通过一个 need 变量记录对右括号的需求数,根据 need 的变化来判断是否需要插入
1) 比如说当 s = ")",我们肯定需要插入一个左括号让 s = "()",但是由于一个左括号需要两个右括号,所以对右括号的需求量变为 1:
if (s[i] == ')') {
    need--;
    // 说明右括号太多了
    if (need == -1) {
        // 需要插入一个左括号
        res++;
        // 同时,对右括号的需求变为 1
        need = 1;
    }
}

另外,当遇到左括号时,若对右括号的需求量为奇数,需要插入 1 个右括号。因为一个左括号需要两个右括号嘛,右括号的需求必须是偶数,这一点也是本题的难点。
要及时处理 when input : ()()))
// when input : ()()))
if (s[i] == '(') {
    need += 2;
    if (need % 2 == 1) {
        // 插入一个右括号
        res++;
        // 对右括号的需求减一
        need--;
    }
}

solution:

public int minInsertions(String s) {
    int res = 0, need = 0;

    for (int i = 0; i < s.length(); i++) {
        if (s.charAt(i) == '(') {
            need += 2;
            if (need % 2 == 1) {
                res++;
                need--;
            }
        }

        if (s.charAt(i) == ')') {
            need--;
            if (need == -1) {
                res++;
                need = 1;
            }
        }
    }

    return res + need;
}

Contents