方法一:动态规划
解题思路:
结合题目,有最长这个字眼,可以考虑尝试使用动态规划进行分析。这是一个最值型动态规划的题目。
动态规划题目分析的 4 个步骤:
确定状态
研究最优策略的最后一步
化为子问题
转移方程
根据子问题定义得到
初始条件和边界情况
计算顺序
首先,我们定义一个 dp[] 数组,其中第 i 个元素表示以下标为 i 的字符结尾的最长有效子字符串的长度。
确定状态:
最后一步:
对于最优的策略,一定有最后一个元素 s[i].
所以,我们先看第 i 个位置,这个位置的元素 s[i] 可能有如下两种情况:
-
s[i] == ′(′ :此时,s[i] 无法和其之前的元素组成有效的括号对,所以,dp[i] = 0。
-
s[i] == ′)′ :此时,需要看其前面的元素来判断是否形成有效括号对。
情况1:
s[i−1] == ′(′,即 s[i] 和 s[i−1] 组成一对有效括号,有效括号长度新增长度2,i 位置的最长有效括号长度为其前2个位置的最长括号长度加上当前位置新增的2,我们无需知道 i−2 位置的字符是否可以组成有效括号对。那么有:dp[i] = dp[i−2] + 2
情况2:s[i−1] == ′)′,这种情况下,如果前面有和s[i]组成有效括号对的字符,即形如((…)),这样的话,就要求s[i−1]位置必然是有效的括号对,否则s[i]无法和前面的字符组成有效括号对。
这时,我们只需要找到和s[i]配对的位置,并判断其是否是 ( 即可。和其配对的位置为:i−dp[i−1]−1。
如果:s[i−dp[i−1]−1] == ′(′ :
有效括号长度新增长度2,i 位置的最长有效括号长度为 i-1 位置的最长括号长度加上当前位置新增的2,那么有:
dp[i] = dp[i−1] + 2
值得注意的是,i−dp[i−1]−1 和 i 组成了有效括号对,这将是一段独立的有效括号序列,如果之前的子序列是形如 ()() 这种序列,那么当前位置的最长有效括号长度还需要加上这一段。所以:dp[i] = dp[i−1] + dp[i−dp[i−1]−2] + 2
子问题:
根据上面的分析,我们得到了如下两个计算公式:
dp[i] = dp[i−2] + 2
dp[i] = dp[i−1] + dp[i−dp[i−1]−2] + 2
那么,求dp[i]就变成了求dp[i−1]、 dp[i−2]、dp[i−dp[i−1]−2]的子问题。
这样状态也明确了:设dp[] 数组,其中第 i 个元素表示以下标为 i 的字符结尾的最长有效子字符串的长度。
转移方程:
子问题明确后,转移方程直接由子问题得到:
if s[i] == '(' :
dp[i] = 0
if s[i] == ')' :
if s[i - 1] == '(' :
dp[i] = dp[i - 2] + 2 #要保证i - 2 >= 0
if s[i - 1] == ')' and s[i - dp[i - 1] - 1] == '(' :
dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2 #要保证i - dp[i - 1] - 2 >=