LeetCode 30 days Challenge - Day 16
本系列將對LeetCode新推出的30天算法挑戰進行總結記錄,旨在記錄學習成果、方便未來查閱,同時望爲廣大網友提供幫助。
Valid Parenthesis String
Given a string containing only three types of characters: ‘(’, ‘)’ and ‘*’, write a function to check whether this string is valid. We define the validity of a string by these rules:
- Any left parenthesis
'('
must have a corresponding right parenthesis')'
. - Any right parenthesis
')'
must have a corresponding left parenthesis'('
. - Left parenthesis
'('
must go before the corresponding right parenthesis')'
. '*'
could be treated as a single right parenthesis')'
or a single left parenthesis'('
or an empty string.- An empty string is also valid.
Example 1:
Input: "()"
Output: True
Example 2:
Input: "(*)"
Output: True
Example 3:
Input: "(*))"
Output: True
Note:
- The string size will be in the range [1, 100].
Solution
題目要求分析:給定一個包含左右圓括號以及星號的字符串,其中星號可以視爲左右圓括號或者空字符串,判斷該字符串是否符合規範。
解法:
本題乍一看像棧結構的經典例題,但本題引入了*
號的特殊性,帶來了一定難度。
首先考慮,*
的引入帶來的影響:
- 假若視爲
(
,那麼需要一個額外的)
進行匹配。 - 假若視爲
)
,那麼能額外匹配一個位置在其之前的(
。 - 假若視爲空,那麼沒有影響。
由於一個符合規範的序列,(
往往先於)
出現,因此可以考慮 *
的不同取值,對需要的 )
數量的影響。
假設,最少需要min_num個 )
,最多需要max_num個 )
,問題轉化爲 *
的不同取值,對上述兩個變量的影響:
- 遇到
(
:min_num、max_num都增加1,這是顯然的。 - 遇到
)
:- max_num減少1,這也是顯然的;
- min_num也減少1,但不少於0(右括號只能匹配其左邊的左括號,如果min_num減少成負數,相當於之後的右括號匹配了之前的左括號,是不符合常理的)。
- 遇到
*
:- 因爲可以看成一個
(
,max_num增加1; - 也可以看成一個
)
,min_num也減少1,但不少於0(理由同上)。 - 看成空串則不會造成影響。
- 因爲可以看成一個
在遍歷過程中,若出現max_num小於0的情況,即出現了一個無法匹配的右括號,直接返回 false
。
最後,因爲min_num是最少需要的條件,判斷min_num是否爲0即可。
注:本題較難理解的是min_num在遍歷過程中不能小於0的原因:小於0則相當於某一個左括號之後的右括號匹配了該左括號,是不符合常理的,這兩個括號就是這種情況“ )( ”。
bool checkValidString(string s) {
int min_num = 0, max_num = 0;
for (char c : s) {
if (c == '(') {
min_num++;
max_num++;
}
else if (c == ')') {
min_num = max(min_num-1, 0);
max_num--;
}
else {
min_num = max(min_num-1, 0);
max_num++;
}
if (max_num < 0) return false;
}
return min_num == 0;
}
2020/4 Karl