【題目描述】
給定一個只包含三種類型字符的字符串:'(',')'和 '*', 編寫一個函數來檢查該字符串是否有效。 我們通過以下規則定義字符串的有效性:
1.任何左括號 '('
必須有一個相應的右括號')'
。
2.任何右括號 ')'
必須有一個相應的左括號'('
。
3.左括號'('
必須在相應的右括號 ')'
之前。
4.*
可以被視爲單個右括號')'
或單個左括號'('
或空字符串。
5.空字符串也有效。
在線評測地址:LintCode 領釦
【樣例】
樣例 1:
輸入: "()"
輸出: true
樣例 2:
輸入: "(*)"
輸出: true
解釋:
'*' 看作是空串.
樣例 3:
輸入: "(*))"
輸出: true
解釋:
'*' 當作'('
【題解】
一道簡單的思維題,考慮到星號在其中的用處就能解決.
- 首先進行最基礎的考慮,(在不考慮星號的情況下)我們必定會選擇位置最接近的左右括號配對,這樣避免了人爲造成的右括號前面沒有左括號匹配的慘劇。因此我們在寫程序進行處理的時候,對於每個右括號判斷前面是否有1個左括號能被他擁有,如果左括號數量不足,這個字符串必定是false,或者當整個串被匹配完之後發現有多餘的左括號,這個字符串同樣是false。
- 接下來考慮有星號的情況:”)”必須由位置在它之前的”(”或”*”匹配,如果”(”或者”*”數量不足導致的false是無法避免的,而如果”(“ 比”)”多,將”(”與”*”優先匹配可以減小false的可能性。舉個例子如樣例3,從左往右遍歷的時候,優先匹配”(”和”*”,遇見第一個”)”,發現沒有單獨的”(”,從”(*”的組合中拆出一個”(“與之匹配,而原先匹配中的*因爲可以等同於不存在便不予理會,接着遇到第二個”)”,拿走剛纔剩餘的”*”。綜上我們可以觀察到,”(”容易受制於”)”而將其與”*”匹配後就很靈活,不僅避免了數量太多帶來的麻煩,也能在和*匹配後再次提供自身給”)”進行匹配。而如果這樣匹配結束還有多餘的”(”則必定false
- 我們設l(left)爲必須被右括號匹配的左括號數量,cp(couple)爲前面左括號和星號數量。遍歷字符串,遇到左括號和星號的時候,cp++; 遇到右括號的時候cp--; 遇到星號,默認先於前面的左括號(l>0)匹配,此時(l—),遇到右括號,默認先與前面必須與右括號匹配的左括號匹配,此時(l—;cp—;)或者在支援兵中考慮(cp—) 注意cp是前方左右的左括號和星號數量,一旦cp<0即false. 匹配完發現(l>0)即多出了左括號,也爲false。剩下的情況就是true了
public class Solution {
/**
* @param s: the given string
* @return: whether this string is valid
*/
public boolean checkValidString(String s) {
// Write your code here
int len=s.length();
int l=0, cp=0;
for (int i=0; i<len; i++) {
if (s.charAt(i)=='(') {
l++;
cp++;
} else if (s.charAt(i)=='*') {
if (l>0) {
l--;
}
cp++;
} else {
if (l>0) l--;
cp--;
if (cp<0) return false;
}
}
if (l==0)
return true;
else
return false;
}
}
更多語言代碼參見: 九章算法