zoukankan      html  css  js  c++  java
  • 【LeetCode每日一题】2020.7.04 32. 最长有效括号

    32. 最长有效括号

    给定一个只包含 '('')' 的字符串,找出最长的包含有效括号的子串的长度。

    示例:

    输入: "(()"
    输出: 2
    解释: 最长有效括号子串为 "()"

    输入: ")()())"
    输出: 4
    解释: 最长有效括号子串为 "()()"

    分析:

    ​ 本题可以用动态规划解决。动态规划的结构是,括号字符串的下标i,dp[i]则表示前i个字符中最长有效括号的长度

    ​ 接着考虑转移方程,

    1. (s[i] == ')' and s[i - 1] == '('):

      可以判断出至少有一对匹配成功,如"......()......"。

      如果字符串为"...((()",则也是只有一对匹配。

      但如果字符串为"...()()()",则(dp[i] = dp[i - 2] + 2),即将之前的有效结果加上。

      归纳一下,即:

      (dp[i] = dp[i - 2] + 2, if s[i] == ')' and s[i - 1]=='(')

      • 同时应该注意边界条件
    2. 如果字符串类似"...((()))",对于最后一个下标如何进行状态转移?

      首先,最里层嵌套括号对右括号dp结果应该为2,接着到第二层括号的右括号")",往左寻找是否有对应的左括号"("。如何寻找那个应该与他对应的左括号呢?只要下标减去中间有效括号的长度即可。同时,应该注意查找前面是否还有一段有效括号。即:

      (dp[i] = egin{cases}dp[i-1] + 2 ext{, if s[i] == ')' and s[i-1] == ')' and s[i - s[i - 1] - 1] == '('} end{cases})

      • 同时应该注意边界条件

    ​ 官方题解还给出了利用 来判断括号匹配关系,以及一种 不需要额外空间的方法。

    代码(Golang):

    // 一、动态规划:
    func longestValidParentheses(s string) int {
    	maxAns := 0
    	dp := make([]int, len(s))
    	for i := 1; i < len(s); i++ {
    		if s[i] == ')' {
    			if s[i - 1] == '(' {
    				if i >= 2 {
    					dp[i] = dp[i - 2] + 2
    				} else {
    					dp[i] = 2
    				}
    			} else if i - dp[i - 1] > 0 && s[i - dp[i - 1] - 1] == '(' {
    				if i - dp[i - 1] >= 2 {
    					dp[i] = dp[i - 1] + dp[i - dp[i - 2] - 2] + 2
    				} else {
    					dp[i] = dp[i - 1] + 2
    				}
    			}
    			maxAns = max(maxAns, dp[i])
    		}
    	}
    }
    
    func max(nums ...int) int {
    	max := nums[0]
    	for i := 1; i < len(nums); i++ {
    		if nums[i] > max {
    			max = nums[i]
    		}
    	}
    	return max
    }
    
    
    // 二、栈:
    func longestValidParentheses1(s string) int {
    	maxAns := 0
    	var stack []int
    	stack = append(stack, -1)
    	for i := 0; i < len(s); i++ {
    		if s[i] == '(' {
    			stack = append(stack, i)
    		} else {
    			stack = stack[:len(stack) - 1]
    			if len(stack) == 0 {
    				stack = append(stack, i)
    			} else {
    				maxAns = max(maxAns, i - stack[len(s) - 1])
    			}
    		}
    	}
    	return maxAns
    }
    
    
    // 三、不需要额外的空间:
    func longestValidParentheses2(s string) int {
    	left, right, maxLength := 0, 0, 0
    	for i := 0; i < len(s); i++ {
    		if s[i] == '(' {
    			left++
    		} else {
    			right++
    		}
    	}
    	if left == right {
    		maxLength = max(maxLength, 2 * right)
    	} else if left > right {
    		left, right = 0, 0
    	}
    	return maxLength
    }
    
  • 相关阅读:
    java学习
    瓜娃《guava》api快速入门
    List,set,Map 的用法和区别
    css selector
    字节流与字符流区别
    jsoup的elements类
    javaio-printwriter
    map遍历的四种方法
    kafka集群和zookeeper集群的部署,kafka的java代码示例
    Ubuntu12.04安装中文字体(转)
  • 原文地址:https://www.cnblogs.com/enmac/p/13262590.html
Copyright © 2011-2022 走看看