合法的括号序列 | 记忆化搜索 Go
合法的括号序列
https://www.nowcoder.com/practice/cd3c583ac7054a18b164fbd4ec3247c4
题意
给定一个仅包含'('、')'和'?'三种字符构成的字符串,'?'字符可以代替左括号或者右括号。请问该字符串可以代表多少种不同的合法括号序列?
思路
看基本上都写的dp,来个记忆化搜索的代码吧
每个?字符都有两种可能,填左括号或是填右括号,可以枚举填哪个进行记忆化搜索
如何判断是合法的括号序列?只需要维护左括号比右括号多了几个就可以,也就是当前没有配对的右括号个数。假设为val,如果当前是左括号,那么下一次dfs的参数肯定是val+1;如果当前是右括号,下一次dfs参数是val-1,表示可以配对一个左括号。注意这里其实会有不合法情况,就是其实左边是没有左括号的,也就是val为负数的情况,需要在dfs开始就判断下。
边界条件就是如果遍历完了所有的字符串,如果左括号和右括号一样多,就是合法的,返回1;否则,返回0
这里是从1到n写的记忆化搜索,也可以从n到1,一样的思路
注意取模
package main import "fmt" func main() { /* 给定一个仅包含'('、')'和'?'三种字符构成的字符串,'?'字符可以代替左括号或者右括号。请问该字符串可以代表多少种不同的合法括号序列? */ const MOD = 1_000_000_007 var s string fmt.Scan(&s) n := len(s) s = " " + s var dfs func(int, int) int /* 子问题:如果当前字符是?的话填什么 可以填左括号 也可以填右括号 两种选择 val表示没有配对的左括号数量 */ dp := make([][]int, n+1) for i := 1; i <= n; i ++ { dp[i] = make([]int,n+1) for j := 0; j <= n; j ++{ dp[i][j] = -1 } } dfs = func(idx int, val int) int { if val < 0 { return 0 } if idx == n+1 { //结束 if val == 0 { return 1 } else { return 0 } } if dp[idx][val] != -1 { return dp[idx][val] } var res = 0 if s[idx] == '?' { //这一位填( res = (res + dfs(idx+1, val+1)) % MOD //这一位填) res = (res + dfs(idx + 1, val - 1 )) % MOD }else if s[idx] == '(' { res = dfs(idx+1,val+1) }else{ res = dfs(idx+1,val-1) } dp[idx][val] = res return res } fmt.Println(dfs(1,0)) }#牛客创作赏金赛#
15天大厂真题带刷Go题解 文章被收录于专栏
15天大厂真题带刷Golang题解