【LeetCode每日一题】2022-10-09 856. 括号的分数 三种方案 Java实现


题目

在这里插入图片描述

我的思路 错误的

先想到用栈,但是,没想通,换成了计数…

记录遇到的左括号的数量,如果遇到的左括号的数量不为零,继续匹配右括号的数量【右括号的数量只可能小于等于左括号的数量】,按照右括号的数量开计算【比如先遇到3个左括号,再遇到2个右括号,则说明有两个括号嵌套,需要乘以2】,按照左括号、右括号匹配,最后还剩下右括号,需要乘以相应的倍数,不过,下面的代码没办法判断,最后剩下的右括号与之匹配的左括号是在什么地方…

默认,括号扩在最外层
在这里插入图片描述

class Solution {
    public int scoreOfParentheses(String s) {
        int len = s.length();
        int left;
        int i = 0;
        int res = 0;
        int temp;
        while (i < len) {
            left = 0;
            while (i < len && s.charAt(i) == '(') {
                i++;
                left++;
            }
            if (left != 0) {
                temp = left;
                while (temp > 0 && s.charAt(i) == ')') {
                    temp--;
                    i++;
                }
                if (temp == 0) {
                    res += Math.pow(2, left - 1);
                } else {
                    res += Math.pow(2, left - temp - 1);
                }
            } else {
                break;
            }
        }
        res *= Math.pow(2, len - i);
        return res;

    }
}

官方思路

方案一 分治

根据题意,一个平衡括号字符串s可以被分解为A+B或(A)的形式,因此我们可以对s进行分解,分而治之

如何判断s应该分解为A+B或(A)的哪一种呢?将左括号记为1,右括号记为-1

  • 如果s的某个非空前缀对应的和bal=0,那么这个前缀就是一个平衡括号字符串
  • 如果该前缀长度等于s的长度,那么s可以分解为(A)的形式
  • 否则s可以分解为A+B的形式,其中A为该前缀。将s分解之后,我们递归地求解子问题,并且s的长度为2时,分数为1

在这里插入图片描述


class Solution {
    public int scoreOfParentheses(String s) {
        if (s.length() == 2) {
            return 1;
        }
        int sum = 0;
        int n = s.length();
        int len = 0;
        for (int i = 0; i < n; i++) {

            if (s.charAt(i) == '(') {
                sum++;
            } else {
                sum--;
            }

            //s的某个非空前缀对应的和为0
            if (sum == 0) {
                len = i + 1;
                break;
            }
        }

        //如果该前缀长度等于s的长度,那么可分解为(A)
        if (len == n) {
            return 2 * scoreOfParentheses(s.substring(1, n - 1));
        }
        //如果前缀长度不等于s,那么可分解为A+B
        return scoreOfParentheses(s.substring(0, len)) + scoreOfParentheses(s.substring(len, n));
    }
}

方案二 栈(个人觉得比较难理解)

把平衡字符串s看作是一个空字符串加上s本身,并且定义空字符串的分数为0。使用栈stack记录平衡字符串的分数,在开始之前要压入分数为0的空字符串

在遍历字符串s的过程中:

  • 遇到左括号,需要计算左括号内部的子平衡括号字符串A的分数,我们也需要先压入分数0,表示A前面空字符串的分数
  • 遇到右括号,说明该右括号内部的子平衡括号字符串A的分数已经计算出来了,我们将它弹出栈,并保存到变量v中。如果v=0,那么说明平衡括号字符串A是空串,(A)的分数为1,否则(A)的分数为2v,然后将(A)的分数加到栈顶元素上

遍历结束后,栈顶元素保存的就是s的分数

在这里插入图片描述

import java.util.Stack;

class Solution {
    public int scoreOfParentheses(String s) {
        Stack<Integer> st = new Stack<>();
        st.push(0);
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                st.push(0);
            } else {
                int v = st.pop();
                int top = st.pop() + Math.max(2 * v, 1);
                st.push(top);
            }
        }
        return st.peek();
    }
}

方案三 计算最终得分(推荐)

根据题意,s的分数与1分()有关,对于每个(),它的最终得分与它所处的深度有关,如果深度为bal,那么它的最终分数为bal,我们统计所有分()的最终分数即可
在这里插入图片描述

class Solution {
    public int scoreOfParentheses(String s) {
        int bal = 0;
        int n = s.length();
        int res = 0;
        for (int i = 0; i < n; i++) {
            if (s.charAt(i) == '(') {
                bal++;
            } else {
                bal--;
            }
            if (s.charAt(i) == ')' && s.charAt(i - 1) == '(') {
                res += (1 << bal);
            }
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值