解题思路
看见这种需要尝试的题果断回溯法!
我们先想想什么样的字符串是括号匹配的,完整字符串必须是左括号数目等于右括号数目还要等于给定的n,并且从头开始的任意一个子串(不是子序列,子串必须是连续的)必须为左括号数目不小于右括号数目。前者没什么好说的,完整字符串中左右括号数目都不匹配肯定是错误的,那后者应该如何理解呢?
如果你做过“20.括号匹配”这道题会很容易理解接下来的说法。我们用一个栈来存放加入到字符串中的左括号,每当我们把右括号加入到字符串中时就从栈中弹出一个左括号来保证左右括号的匹配,所以在组成完整字符串前,栈中一定是非空的,如果刚好弹出一个左括号后导致栈空,那么下一次给字符串添加括号时,我们只能添加一个左括号而不能添加右括号,因为栈中是空的添加右括号就不会满足括号匹配的要求了。所以说在组成一个完整的字符串前,左括号数目一定是大于等于右括号数目的,即从头开始的任意一个子串都是左括号数不小于右括号数。
根据上面的分析,我们在DFS的过程中需要记录下当前字符串有几个左括号,有几个右括号,如果左括号的数目小于n,那么我们就可以尝试字符串加个左括号;如果右括号数小于左括号数,我们就可以尝试字符串加个右括号。当左括号数等于n时,我们只能添加右括号;当左括号数等于右括号数但不等于n时,我们只能添加左括号;当右括号数等于n时我们就产生了一个满足括号匹配的字符串,加到res数组中。
AC代码
func generateParenthesis(n int) (res []string) {
var DFS func(string,int,int)
DFS=func(str string,leftCount,rightCount int){
if rightCount==n{
res=append(res,str)
return
}
if leftCount<n{
DFS(str+"(",leftCount+1,rightCount)
}
if rightCount<leftCount{
DFS(str+")",leftCount,rightCount+1)
}
}
DFS("",0,0)
return res
}
感悟
感觉自己用Go函数值写回溯越来越熟练了,看来多刷题真的会提升自己呀!