Given a balanced parentheses string S
, compute the score of the string based on the following rule:html
()
has score 1AB
has score A + B
, where A and B are balanced parentheses strings.(A)
has score 2 * A
, where A is a balanced parentheses string.Example 1:git
Input: "()" Output: 1
Example 2:github
Input: "(())" Output: 2
Example 3:優化
Input: "()()" Output: 2
Example 4:code
Input: "(()(()))" Output: 6
Note:htm
S
is a balanced parentheses string, containing only (
and )
.2 <= S.length <= 50
這道題給了咱們一個只有括號的字符串,一個簡單的括號值1分,並排的括號是分值是相加的關係,包含的括號是乘的關係,每包含一層,都要乘以個2。題目中給的例子很好的說明了題意,博主最早嘗試的方法是遞歸來作,思路是先找出每個最外層的括號,再對其中間的總體部分調用遞歸,好比對於 "()(())" 來講,第一個最外邊的括號是 "()",其中間爲空,對空串調用遞歸返回0,可是結果 res 仍是加1,這個特殊的處理後面會講到。第二個最外邊的括號是 "(())" 的外層括號,對其中間的 "()" 調用遞歸,返回1,再乘以2,則獲得 "(())" 的值,而後把兩者相加,就是最終須要的結果了。找部分合法的括號字符串的方法就是使用跟以前那道題 Valid Parentheses 的相同的方法,使用一個計數器,遇到左括號,計數器自增1,反之右括號計數器自減1,那麼當計數器爲0的時候,就是一個合法的字符串了,咱們對除去最外層的括號的中間內容調用遞歸,而後把返回值乘以2,並和1比較,取兩者間的較大值加到結果 res 中,這是由於假如中間是空串,那麼返回值是0,乘以2仍是0,可是 "()" 的分值應該是1,因此累加的時候要跟1作比較。以後記得要更新i都正確的位置,參見代碼以下:blog
解法一:遞歸
class Solution { public: int scoreOfParentheses(string S) { int res = 0, n = S.size(); for (int i = 0; i < n; ++i) { if (S[i] == ')') continue; int pos = i + 1, cnt = 1; while (cnt != 0) { (S[pos++] == '(') ? ++cnt : --cnt; } int cur = scoreOfParentheses(S.substr(i + 1, pos - i - 2)); res += max(2 * cur, 1); i = pos - 1; } return res; } };
咱們也可使用迭代來作,這裏就要藉助棧 stack 來作,由於遞歸在調用的時候,其實也是將當前狀態壓入棧中,等遞歸退出後再從棧中取出以前的狀態。這裏的實現思路是,遍歷字符串S,當遇到左括號時,將當前的分數壓入棧中,並把當前得分清0,若遇到的是右括號,說明此時已經造成了一個完整的合法的括號字符串了,並且除去外層的括號,內層的得分已經算出來了,就是當前的結果 res,此時就要乘以2,而且要跟1比較,取兩者中的較大值,這樣操做的緣由已經在上面解法的講解中解釋過了。而後還要加上棧頂的值,由於棧頂的值是以前合法括號子串的值,跟當前的是並列關係,因此是相加的操做,最後不要忘了要將棧頂元素移除便可,參見代碼以下:leetcode
解法二:字符串
class Solution { public: int scoreOfParentheses(string S) { int res = 0; stack<int> st; for (char c : S) { if (c == '(') { st.push(res); res = 0; } else { res = st.top() + max(res * 2, 1); st.pop(); } } return res; } };
咱們能夠對空間複雜度進行進一步的優化,並不須要使用棧去保留全部的中間狀況,能夠只用一個變量 cnt 來記錄當前在第幾層括號之中,由於本題的括號累加值是有規律的,"()" 是1,由於最中間的括號在0層括號內,2^0 = 1。"(())" 是2,由於最中間的括號在1層括號內,2^1 = 2。"((()))" 是4,由於最中間的括號在2層括號內,2^2 = 4。所以類推,其實只須要統計出最中間那個括號外變有幾個括號,就能夠直接算出整個多重包含的括號字符串的值,參見代碼以下:
解法三:
class Solution { public: int scoreOfParentheses(string S) { int res = 0, cnt = 0, n = S.size(); for (int i = 0; i < n; ++i) { (S[i] == '(') ? ++cnt : --cnt; if (S[i] == ')' && S[i - 1] == '(') res += (1 << cnt); } return res; } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/856
相似題目:
參考資料:
https://leetcode.com/problems/score-of-parentheses/
https://leetcode.com/problems/score-of-parentheses/discuss/141777/C%2B%2BJavaPython-O(1)-Space