您好,登錄后才能下訂單哦!
今天小編給大家分享一下C++怎么實(shí)現(xiàn)最長(zhǎng)有效括號(hào)的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。
Given a string containing just the characters "(" and ")", find the length of the longest valid (well-formed) parentheses substring.
Example 1:
Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"
Example 2:
Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"
這道求最長(zhǎng)有效括號(hào)比之前那道 Valid Parentheses 難度要大一些,這里還是借助棧來(lái)求解,需要定義個(gè) start 變量來(lái)記錄合法括號(hào)串的起始位置,遍歷字符串,如果遇到左括號(hào),則將當(dāng)前下標(biāo)壓入棧,如果遇到右括號(hào),如果當(dāng)前棧為空,則將下一個(gè)坐標(biāo)位置記錄到 start,如果棧不為空,則將棧頂元素取出,此時(shí)若棧為空,則更新結(jié)果和 i - start + 1 中的較大值,否則更新結(jié)果和 i - st.top() 中的較大值,參見(jiàn)代碼如下:
解法一:
class Solution { public: int longestValidParentheses(string s) { int res = 0, start = 0, n = s.size(); stack<int> st; for (int i = 0; i < n; ++i) { if (s[i] == "(") st.push(i); else if (s[i] == ")") { if (st.empty()) start = i + 1; else { st.pop(); res = st.empty() ? max(res, i - start + 1) : max(res, i - st.top()); } } } return res; } };
還有一種利用動(dòng)態(tài)規(guī)劃 Dynamic Programming 的解法。這里使用一個(gè)一維 dp 數(shù)組,其中 dp[i] 表示以 s[i-1] 結(jié)尾的最長(zhǎng)有效括號(hào)長(zhǎng)度(注意這里沒(méi)有對(duì)應(yīng) s[i],是為了避免取 dp[i-1] 時(shí)越界從而讓 dp 數(shù)組的長(zhǎng)度加了1),s[i-1] 此時(shí)必須是有效括號(hào)的一部分,那么只要 dp[i] 為正數(shù)的話,說(shuō)明 s[i-1] 一定是右括號(hào),因?yàn)橛行Юㄌ?hào)必須是閉合的。當(dāng)括號(hào)有重合時(shí),比如 "(())",會(huì)出現(xiàn)多個(gè)右括號(hào)相連,此時(shí)更新最外邊的右括號(hào)的 dp[i] 時(shí)是需要前一個(gè)右括號(hào)的值 dp[i-1],因?yàn)榧偃?dp[i-1] 為正數(shù),說(shuō)明此位置往前 dp[i-1] 個(gè)字符組成的子串都是合法的子串,需要再看前面一個(gè)位置,假如是左括號(hào),說(shuō)明在 dp[i-1] 的基礎(chǔ)上又增加了一個(gè)合法的括號(hào),所以長(zhǎng)度加上2。但此時(shí)還可能出現(xiàn)的情況是,前面的左括號(hào)前面還有合法括號(hào),比如 "()(())",此時(shí)更新最后面的右括號(hào)的時(shí)候,知道第二個(gè)右括號(hào)的 dp 值是2,那么最后一個(gè)右括號(hào)的 dp 值不僅是第二個(gè)括號(hào)的 dp 值再加2,還可以連到第一個(gè)右括號(hào)的 dp 值,整個(gè)最長(zhǎng)的有效括號(hào)長(zhǎng)度是6。所以在更新當(dāng)前右括號(hào)的 dp 值時(shí),首先要計(jì)算出第一個(gè)右括號(hào)的位置,通過(guò) i-3-dp[i-1] 來(lái)獲得,由于這里定義的 dp[i] 對(duì)應(yīng)的是字符 s[i-1],所以需要再加1,變成 j = i-2-dp[i-1],這樣若當(dāng)前字符 s[i-1] 是左括號(hào),或者j小于0(說(shuō)明沒(méi)有對(duì)應(yīng)的左括號(hào)),或者 s[j] 是右括號(hào),此時(shí)將 dp[i] 重置為0,否則就用 dp[i-1] + 2 + dp[j] 來(lái)更新 dp[i]。這里由于進(jìn)行了 padding,可能對(duì)應(yīng)關(guān)系會(huì)比較暈,大家可以自行帶個(gè)例子一步一步執(zhí)行,應(yīng)該是不難理解的,參見(jiàn)代碼如下:
解法二:
class Solution { public: int longestValidParentheses(string s) { int res = 0, n = s.size(); vector<int> dp(n + 1); for (int i = 1; i <= n; ++i) { int j = i - 2 - dp[i - 1]; if (s[i - 1] == "(" || j < 0 || s[j] == ")") { dp[i] = 0; } else { dp[i] = dp[i - 1] + 2 + dp[j]; res = max(res, dp[i]); } } return res; } };
此題還有一種不用額外空間的解法,使用了兩個(gè)變量 left 和 right,分別用來(lái)記錄到當(dāng)前位置時(shí)左括號(hào)和右括號(hào)的出現(xiàn)次數(shù),當(dāng)遇到左括號(hào)時(shí),left 自增1,右括號(hào)時(shí) right 自增1。對(duì)于最長(zhǎng)有效的括號(hào)的子串,一定是左括號(hào)等于右括號(hào)的情況,此時(shí)就可以更新結(jié)果 res 了,一旦右括號(hào)數(shù)量超過(guò)左括號(hào)數(shù)量了,說(shuō)明當(dāng)前位置不能組成合法括號(hào)子串,left 和 right 重置為0。但是對(duì)于這種情況 "(()" 時(shí),在遍歷結(jié)束時(shí)左右子括號(hào)數(shù)都不相等,此時(shí)沒(méi)法更新結(jié)果 res,但其實(shí)正確答案是2,怎么處理這種情況呢?答案是再反向遍歷一遍,采取類(lèi)似的機(jī)制,稍有不同的是此時(shí)若 left 大于 right 了,則重置0,這樣就可以 cover 所有的情況了,參見(jiàn)代碼如下:
解法三:
class Solution { public: int longestValidParentheses(string s) { int res = 0, left = 0, right = 0, n = s.size(); for (int i = 0; i < n; ++i) { (s[i] == "(") ? ++left : ++right; if (left == right) res = max(res, 2 * right); else if (right > left) left = right = 0; } left = right = 0; for (int i = n - 1; i >= 0; --i) { (s[i] == "(") ? ++left : ++right; if (left == right) res = max(res, 2 * left); else if (left > right) left = right = 0; } return res; } };
以上就是“C++怎么實(shí)現(xiàn)最長(zhǎng)有效括號(hào)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。