[LeetCode] 856. Score of Parentheses 括號的分數



Given a balanced parentheses string `S`, compute the score of the string based on the following rule:
  • () has score 1
  • AB 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:

Input: "()"
Output: 1

Example 2:

Input: "(())"
Output: 2

Example 3:

Input: "()()"
Output: 2

Example 4:

Input: "(()(()))"
Output: 6

Note:

  1. S is a balanced parentheses string, containing only ( and ).
  2. 2 <= S.length <= 50

這道題給了我們一個只有括號的字符串,一個簡單的括號值1分,並排的括號是分值是相加的關系,包含的括號是乘的關系,每包含一層,都要乘以個2。題目中給的例子很好的說明了題意,博主最先嘗試的方法是遞歸來做,思路是先找出每一個最外層的括號,再對其中間的整體部分調用遞歸,比如對於 "()(())" 來說,第一個最外邊的括號是 "()",其中間為空,對空串調用遞歸返回0,但是結果 res 還是加1,這個特殊的處理后面會講到。第二個最外邊的括號是 "(())" 的外層括號,對其中間的 "()" 調用遞歸,返回1,再乘以2,則得到 "(())" 的值,然后把二者相加,就是最終需要的結果了。找部分合法的括號字符串的方法就是使用跟之前那道題 [Valid Parentheses](http://www.cnblogs.com/grandyang/p/4424587.html) 的相同的方法,使用一個計數器,遇到左括號,計數器自增1,反之右括號計數器自減1,那么當計數器為0的時候,就是一個合法的字符串了,我們對除去最外層的括號的中間內容調用遞歸,然后把返回值乘以2,並和1比較,取二者間的較大值加到結果 res 中,這是因為假如中間是空串,那么返回值是0,乘以2還是0,但是 "()" 的分值應該是1,所以累加的時候要跟1做比較。之后記得要更新i都正確的位置,參見代碼如下:
解法一:
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比較,取二者中的較大值,這樣操作的原因已經在上面解法的講解中解釋過了。然后還要加上棧頂的值,因為棧頂的值是之前合法括號子串的值,跟當前的是並列關系,所以是相加的操作,最后不要忘了要將棧頂元素移除即可,參見代碼如下:
解法二:
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


類似題目:

Valid Parentheses


參考資料:

https://leetcode.com/problems/score-of-parentheses/

https://leetcode.com/problems/score-of-parentheses/discuss/141777/C%2B%2BJavaPython-O(1)-Space


[LeetCode All in One 題目講解匯總(持續更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM