JS击败94%,Hard题想不到动态规划,那就用数组和栈试试

Problem: 32. 最长有效括号

  1. 思路
  2. 解题方法
  3. 复杂度
  4. Code

思路

做热题100做到的,看到是Hard的dp,直接投降了,寻思另一种写法。于是去评论区逛了下,有位同学提到了用栈+合并区间的思路,于是以此为线索,开始思考此题的解法。

解题方法

个人习惯阅读题干,将信息消化,而后逐步击破。此题要求我们求【最长有效括号】

那么可以拆解成2个问题

  • 有效括号
  • 最长

我的想法是通过一个栈去存储字符串中的()(注意,存的是inedx),当遍历到)时,判断此时栈顶元素(即stk.pop())是否是(,如果是,则用一个结果数组(即result)去记录此时出现的有效括号()index

拿示例2举个例子:

")()())"

  1. 遍历此字符串,当遍历到(时,此时往stkpush它的index,即1

  2. 而后继续遍历,当遍历到)时,判断栈顶元素是否是(,代码判断如下:

    js 复制代码
         if (s[i] === ')') {
          let top = stk.pop()
          // 即 s[1] === '('
          if (s[top] === '(') {
    
              result.push([top, i])
          }
      }
  3. 如果是,则代表我们遇到了1个有效括号,此时往result里存储此括号的左右下标。

    js 复制代码
              // 即 result.push([1,2])
              result.push([top, i])
          
      

当我们遍历完毕整个s之后,我们就会得到这样一个result数组:[[1,2],[3,4]]

接下来我们要做的就是合并区间,可以参考一下这道题哦:56. 合并区间

不过比这题还要多一种合并区间的情况,即就算区间不重叠,但是相邻的话,也要合并。

即,我们要合并重叠区间,也要合并相邻区间

回到此题,我们对result执行合并区间的操作,得到最终的target数组:[1,4],此时,最长 这个问题也迎刃而解了,就是4 - 1 + 1,即 4

这里方便理解我再举1个例子:

"((((()))))("

得到的result数组长这样:

[ [ 4, 5 ], [ 3, 6 ], [ 2, 7 ], [ 1, 8 ], [ 0, 9 ] ]

按照左边界排序一下

[ [ 0, 9 ], [ 1, 8 ], [ 2, 7 ], [ 3, 6 ], [ 4, 5 ] ]

然后执行合并区间的操作,得到target

[0,9],最终最长的答案也就是10

复杂度

时间复杂度:

O(n)

空间复杂度:

O(n)

Code

js 复制代码
/**
 * @param {string} s
 * @return {number}
 */
var longestValidParentheses = function (s) {
    let stk = []
    let result = [];
    for (let i = 0; i < s.length; i++) {
        if (s[i] === ")" && !stk.length) {
            continue;
        }
        if (s[i] === '(') {
            stk.push(i);
        }
        if (s[i] === ')') {
            let top = stk.pop()
            if (s[top] === '(') {

                result.push([top, i])
            }
        }
    }


    // 开始合并数组
    result.sort((a, b) => a[0] - b[0])

    let targets = [];
    let ans = 0;
    // 每次合并完数组之后,计算一次长度,和ans做一次比较,取最大的。
    for (let i = 0; i < result.length; i++) {
        if (!targets.length) {
            let temp = result[i][1] - result[i][0] + 1
            ans = Math.max(ans, temp)
            targets = result[i]
        }
        else {

            if (targets[1] > result[i][1]) {
                let temp = targets[1] - targets[0] + 1
                ans = Math.max(ans, temp)

            }

            if (targets[1] + 1 === result[i][0]) {
                let temp = result[i][1] - targets[0] + 1
                ans = Math.max(ans, temp)
                targets = [targets[0], result[i][1]]
            }

            if (targets[1] < result[i][0] - 1) {
                targets = result[i]
                let temp = result[i][1] - result[i][0] + 1
                ans = Math.max(ans, temp)
            }
        }
    }



    return ans;
};
相关推荐
luj_17684 小时前
星火科技助力边远地区防病攻坚
c语言·开发语言·c++·经验分享·算法
geats人山人海6 小时前
数据结构第六章c语言 树的存储下二叉树的概念和存储
c语言·数据结构·算法
漂流瓶jz7 小时前
UVA-12627 奇怪的气球膨胀 题解答案代码 算法竞赛入门经典第二版
算法·图论·递归·aoapc·算法竞赛入门经典·uva·12627
jarvisuni7 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
kobesdu7 小时前
流形上的优化:SO(3)与SE(3)的广义加减法在FAST-LIO中如何简化状态估计
人工智能·算法·fastlio
白狐_7988 小时前
408 数据结构算法题 01:线性表暴力求解保分指南
java·数据结构·算法
乐观勇敢坚强的老彭8 小时前
C++信奥:开关门、开关灯问题
开发语言·c++·算法
冻柠檬飞冰走茶8 小时前
PTA基础编程题目集 7-31 字符串循环左移(C语言实现)
c语言·开发语言·数据结构·算法
Hi李耶8 小时前
【LeetCode】4-寻找两个正序数组的中位数
算法·leetcode·职场和发展
图灵机z8 小时前
【算法提高课】AcWing 1027. 方格取数 长期攻克提高课-day3(3/219)
算法