LeetCode高频题:子串权值定义为,最长有效括号子序列的长度,请你返回字符串s的所有子串权值的和是多少

该博客探讨了LeetCode中的一道高频题目,涉及字符串处理和动态规划。内容包括理解子串权值(最长有效括号子序列的长度),并给出了一种解决思路,但指出该方法存在超时问题,需要通过动态规划进行优化。作者提出了初步的动态规划表格填充方案,但遇到了转移方程的困扰,尚未完成代码实现。博客强调了括号匹配问题在面试中的重要性,并提醒读者要重视基础算法学习和解题能力的提升。
摘要由CSDN通过智能技术生成

LeetCode高频题:子串权值定义为,最长有效括号子序列的长度,请你返回字符串s的所有子串权值的和是多少?

提示:本题是系列LeetCode的150道高频题,你未来遇到的互联网大厂的笔试和面试考题,基本都是从这上面改编而来的题目
互联网大厂们在公司养了一大批ACM竞赛的大佬们,吃完饭就是设计考题,然后去考应聘人员,你要做的就是学基础树结构与算法,然后打通任督二脉,以应对波云诡谲的大厂笔试面试题!
你要是不扎实学习数据结构与算法,好好动手手撕代码,锻炼解题能力,你可能会在笔试面试过程中,连题目都看不懂!比如华为,字节啥的,足够让你读不懂题
在这里插入图片描述

基础知识:
【1】括号匹配问题:判断一个字符串是否为有效的括号匹配
【2】括号匹配问题:括号字符串是否有效匹配,无效的话还需要加多少个括号才能完全匹配
【3】括号匹配问题:括号字符串的最大匹配嵌入深度是多少
【4】括号匹配问题:括号字符串的有效匹配子串最大长度是多少


题目

在这里插入图片描述
在这里插入图片描述


一、审题

示例:如上,注意是子序列,不是子串哦,子串超级困难【看上面【4】,非常重要】


二、解题

分析
())())

你看看这个有效子序列最长的咋搞

其实你中途给统计左括号有几个?left个
然后遇到右括号,如果left>0,则可以消耗一个left括号,配对为一对,right=1记录了
如果遇到右括号,发现left<=0,显然没有办法配对,right就不要增加了

在这里插入图片描述
最长的有效括号子序列长度就是right的2倍,因为配对呗

所以
你只需要遍历给你的字符串s的每一个子串,查上面的最长有效子序列长度,把结果加ans就行

手撕代码:

public static class Main {
        public static void main(String[] args) {
            Scanner in = new Scanner(System.in);
            String s = in.nextLine();//())())
            int ans = 0;
            for (int i = 0; i < s.length(); i++) {
                for (int j = i; j < s.length(); j++) {
                    ans += f(s.substring(i, j + 1));
                }
            }
            System.out.println(ans);
        }

        //最长括号子序列长度
        public static int f(String s){
            int l = 0, r = 0;
            char[] str = s.toCharArray();
            for (int i = 0; i < str.length; i++) {
                if (str[i] == '(') l++;
                else if (l > 0) {
                    l--;
                    r++;
                }
            }
            return r << 1;
        }
    }

测试:
在这里插入图片描述

看看朋友们今天京东的秋招笔试题目好像也不难吧?

据他们说这玩意超时,那看来要用动态规划优化一下

我想了一个方法,就是设计一个dp表

n*n

代表啥意思?dpij是代表字符串s的i–j范围上的最长括号子序列长度
可不就是一个范围上的尝试模型

那么
我们就可以这样填一个表格了
(1)主对角线全0,为啥呢?就i一个字符,没法匹配啊,长度肯定是0
(2)副对角,i必须是左括号(,j必须是右括号),同时成立,dpi,i+1 = 2
在这里插入图片描述
剩下的,按照上面圈1,2,3,–从下往上,每次从左往右去填

最后把右上角所有结果加到ans,相当于就是把所有子串枚举一遍

就是结果

只可惜:
(3)你咋填dpij呢?转移方程不好搞啊

比如:i是),j是(,肯定不行,则dpij=dpi+1,j-1
在这里插入图片描述
比如:i是(,j是),肯定能行,则dpij=dpi+1,j-1 + 2
在这里插入图片描述

但是请问别的情况呢
i=),j=)
i=(,j=(
这俩情况咋整啊?

首先看:i=(,j=(
i是(,你得看看i+1–j里面有没有),多余了才能配对,要是不多,咋搞呢????尴尬,
在这里插入图片描述

目前我还不知道我这么尝试对不对?
后面重新思考思考
尴尬
没完成的代码:
有大佬瞅瞅怎么改进?

public static void main(String[] args) {
            Scanner in = new Scanner(System.in);
            String s = in.nextLine();//())())
            int ans = 0;

            int n = s.length();
            char[] str = s.toCharArray();
            int[][] dp = new int[n][n];//范围L--R上的最长有效括号子序列匹配长度
            //主对角线i=j,那些格子默认0,就一个字符,咋可能有效呢?
            for (int i = 0; i < n - 1; i++) {//副对角线
                dp[i][i + 1] = str[i] == '(' && str[i + 1] == ')' ? 2 : 0;
            }
            for (int i = n - 3; i >= 0; i--) {//倒回来填写
                for (int j = i + 2; j < n; j++) {
                    //如果i是),不行,如果j是(,不行
                    if (str[i] == ')' && str[j] == '(') {
                        dp[i][j] = dp[i + 1][j - 1];
                    }else if (str[i] == '(' && str[j] == ')'){
                        //如果i是(,且j是),长度+2
                        dp[i][j] = dp[i + 1][j - 1] + 2;
                    }else {
                        //如果i是(,可能跟i+1--j配上,长度+2
                        //如果j是),可能跟i--j-1配上,长度+2
                        dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]) + ?;????
                    }
                }
            }
            //刷一遍子串结果
            for (int i = 0; i < s.length(); i++) {
                for (int j = i; j < s.length(); j++) {
                    ans += dp[i][j];
                }
            }
            System.out.println(ans);
        }

总结

提示:重要经验:

1)括号匹配问题,我多次讲过,这是最新的最长有效括号子序列长度,简单,那个最长有效括号子串很难
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰露可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值