有效括號生成

2021-10-04 03:57:33 字數 3399 閱讀 7810

動態規劃法

合法的括號匹配的問題之前已經講解過了,現在再看乙個括號生成的題目。

給出 n 代表生成括號的對數,請你寫出乙個函式,使其能夠生成所有可能的並且有效的括號組合。

例如,給出 n = 3,生成結果為:

既然之前已經分析過合法的括號判斷,那麼只要把n個左括號和n個右括號全排列,然後對排列的結果去做乙個有效驗證,好了,這個問題解決了。但是仔細一分析,判斷乙個括號是否有效,複雜度o(n

)o(n)

o(n)

,生成2n個括號字元的全排列,時間複雜度o(2

2n

)o(2^)

o(22n)

,這很難辦啊。所以全排列的方式行不通。

深度搜尋法

全排列裡面有很多左括號和右括號數目不等的,可以直接排除了,所以浪費了很多判斷。我們可以通過回溯提前把不合理的字元排除掉。但是回溯法只能是逐漸的字串變長,也就是深度優先搜尋的原理。但是我們這個時候在每一次增加括號的時候,我們保證右括號不會超過當前的左括號數目即可。還要保證最終的括號數目,左括號和右括號的數目都是n。

根據這個思想,我們可以去寫**了,我們記錄下當前左括號的數目,記錄下當前右括號的數目,如果左括號大於右括號,且左括號數目小於n,此時我們深度搜尋的路徑包括兩條,新增左括號和右括號。如果左括號數目等於n了,那麼就只有一條路徑,如果左括號數目等於右括號數目了且不等於n,此時只能新增左括號。如果兩者數目相等,且等於n,則可以返回了,已經生成了一組合法的括號字元。整個演算法就是乙個深度遍歷,可以採用遞迴來實現。

python**

class

solution

:def

generateparenthesis

(self,n)

: ans=

self.

max=n

self.backtrack(ans,"",

0,0)

return ans

defbacktrack

(self, ans, cur, left, right)

:if left==self.

max:

')'*

(self.

max- right)

)return

if(leftmax)

: self.backtrack(ans, cur +

'(', left +

1, right)

if rightself.backtrack(ans, cur +

')', left, right +

1)

可以看到,這種方式保證了左括號的數目始終多於右括號,這樣生成出來的一定是合法的括號字串。因為每次生成保證了都是合法的字首,這個複雜度就大大的減少了。

事實上,合法的括號數目,我們在卡特蘭數的應用分析了n個括號的合法種類數就是卡特蘭數列的第n項,我們大致可以根據卡特蘭數的性質,分析問題的規模。我們知道卡特蘭數的漸進上界是o(4

nn

)o\left ( \frac} \right )

o(n​4n

​),而每乙個合法的序列,我們是通過o(n

)o(n)

o(n)

次新增字元生成出來的。

動態規劃法

既然這個問題和卡特蘭數相關,那麼一定可以根據卡特蘭數的特點,一定可以把這個問題轉換成以前所有狀態的窮舉。說的通俗一點就是,如果我們研究問題規模為n,那麼問題規模之和為n-1的兩兩組合一定可以用得上,如果這句話理解不了可以直接跳到下一段。

我們為了降低問題規模,可以考慮在問題規模為n-1的情況上加一對括號,可是這個多出來的一對括號應該往哪加。顯然,我們可以把這個括號加在所有的合法匹配的括號之後。如果合法匹配數為0的時候,我們就把括號加在了最前面,就是()+

dpn−

1()+dp_

()+dpn

−1​,再者我們可以把括號加到一對合法括號後面,也是(dp

1)+d

pn−2

(dp_1)+dp_

(dp1​)

+dpn

−2​依次類推,n-1個合法的括號總共可以分解出n-1種情況。每個情況分為兩部分,前面一部分是dp_i,後面一部分是dp_n-1-i,其實也就是兩部分滿足下標之和為n-1就行。

據此我們可以寫出動態規劃的遞迴式。dpi

="("

+dpj

+")"

+dpi

−j−1

,whe

re

j<

idp_i="(" + dp_j + ")"+dp_, \ where \ jdp

i​="

("+d

pj​+

")"+

dpi−

j−1​

,whe

rej<

i。事實上,幾乎所有的卡特蘭數問題都可以寫成類似的遞推式,對所有兩兩組合為n-1的情況然後窮舉,並做出一定的修改。大家可以記住這個結論,當然也可以寫成數學表示式,我直接寫成程式的表示式即可。下面就可以根據這個表示式寫**。只需要對dpj

dp_j

dpj​

和d pi

−j−1

dp_dp

i−j−

1​做個全排列即可。

python**

class

solution

:# 動態規劃

defgenerateparenthesis

(self, n:

int)

-> list[

str]

: dp=[[

]for i in

range

(n+1)]

dp[0]

=['']

for i in

range(1

,n+1):

for j in

range

(i):

dp[i]

.extend(self.compent(dp[j]

,dp[i-j-1]

))return dp[n]

defcompent

(self, l, r)

: res=

for s1 in l:

for s2 in r:

'('+s1+

')'+s2 )

return res

分析時間複雜度的時候大家需要注意一下,就是雖然這個**寫出來是4個for,但是這個**的時間複雜度不是o(n

4)

o(n^4)

o(n4

),相比於上面的回溯法,其實時間複雜度的指數部分還是保持的,單是求問題規模等於n的情況,時間複雜度就已經達到了o(4

nn

)o\left ( \frac} \right )

o(n​4n​)。

LeetCode 有效括號生成,回溯法的應用

題目描述 給出 n 代表生成括號的對數,請你寫出乙個函式,使其能夠生成所有可能的並且有效的括號組合。題目思路 回溯法 一般排列組合的問題都需要用到遞迴演算法中的回溯思路。這道題是典型的回溯法應用的場景,只不過需要在回溯的過程中新增條件限定,不符合有效的括號組合不進行回溯即可。關於回溯法,這一篇部落格...

有效的括號

題目描述 給定乙個只包括 的字串,判斷字串是否有效。有效字串需滿足 左括號必須用相同型別的右括號閉合。左括號必須以正確的順序閉合。注意空字串可被認為是有效字串。解題思路 坦白來講這道題真的沒什麼思路,掉的坑也比較多,因為審題不認真,最後的一句話,注意空字串可被認為是有效字串。被吃掉了 最後提交的 執...

棧 有效括號

題目鏈結 題目分析 一道水題,利用棧就好了,當遇到 同理,當以上兩種情況都不滿足時,直接無效,後面的不用判斷 否則最後若棧空則有效,否則無效。class solution 配對成功出棧 else if s i top 1 st top top else if s i top 1 st top top...