【算法】Longest Valid Parentheses 最长有效括号

题目

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

Example 1:

Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"

Example 2:

Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"

给出一个只含有 "("、")" 的字符串,寻找字符串中最长的有效括号的长度。

解题思路

这里就需要分析一下 "()" 的特性了:

  1. "()" 的长度为 2
  2. ”()“ 左右位置若存在有效括号,则可以进行拼接
  3. "()" 若有效,且其中间位置存在字符,则中间的字符串也一定为有效括号

依据这三点特性,可以考虑如下思路来寻找最长括号:

  1. 从左到右遍历字符串,找到有效的括号,并计算其本身的长度
    • 以找到 ")" 为 当前标识 ,再寻找与其匹配的 "(",若找到则为有效括号
    • 假设当前有效括号中间含有有效括号M,寻找与其匹配的 "("
      • 找到当前字符 ")" 的位置为 i ,每个有效括号的当前最长长度存进 max[i],
      • 当前位置 i 左移到 有效括号M 的左侧( 左移 max[i-1] + 1 位),即为当前有效括号的 "(" 的位置 j = i - 1 - max[i-1]
      • 当且仅当位置 j 的字符存在且为 "(" 时,当前有效括号的假设才成功,当前有效括号的长度为当前左右括号长度 2 加上 有效括号M 的长度 max[i-1],( 2 + max[i-1])
  2. 由于是从左到右遍历,所以若左边位置为有效括号(有效括号L),计算最长长度时,需要加上 有效括号L 的长度 max[j-1]
  3. 计算完 max[i] 与结果容器 res 做较大值比较,赋较大值给 res
  4. 遍历结束,返回 res 即为最长有效括号的长度

PS: 有效括号M 若存在,其长度为 max[i-1] 有值, 有效括号M 若不存在 max[i-1] 为 0,若 当前有效括号 中间位置没有字符时,i-1 位置为 "(",其在max的值max[i-1]也为 0 ,所以 当前有效括号 中间没有字符时的长度计算方式和 有效括号M 不存在时的计算方式是一致的,用 j = i - 1 - max[i-1] 寻找匹配 "(" 的方式可以同时解决。

代码实现

Runtime: 12 ms
Memory: 20.9 MB

func longestValidParentheses(_ s: String) -> Int {
        let len = s.count
        // 长度小于 2 的时候,成不了一组 () 所以返回 0
        if len < 2 {
            return 0
        }
        // 将 s 转换成数组,方便操作
        let s = Array(s)
        // max 数组 记录当前有效括号最大长度
        var max = Array(repeating: 0, count: len)
        // res 作为结果
        var res = 0
        // 从 1 开始遍历 s
        for i in 1 ..< len {
            // 只有当前字符为 ")" 时,才有可能出现有效括号
            if s[i] == ")" {
                // 用 i 减去 max[i-1] 的中间位置有效括号长度,再减去当前字符长度 1,即为与当前有效括号的 ( 的位置 j
                let j = i - 1 - max[i-1];
                // 只有当 j >= 0,并且 s[j] 为 ( 时,有效括号才匹配
                if j >= 0 && s[j] == "(" {
                    //有效括号匹配,更新 max[i] 的值,当前成对括号长度 2 ,中间位置有效括号长度 max[i-1],左侧有效括号长度 max[j-1],加和在一起
                    max[i] = 2 + max[i-1] + (j > 1 ? max[j-1] : 0)
                    //更新较大值到 res
                    res = max[i] > res ? max[i] : res
                }
            }
        }
        return res
    }

代码地址:https://github.com/sinianshou/EGSwiftLearning

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,427评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,551评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,747评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,939评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,955评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,737评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,448评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,352评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,834评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,992评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,133评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,815评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,477评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,022评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,147评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,398评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,077评论 2 355

推荐阅读更多精彩内容