LeetCode 678. Valid Parenthesis String
題目連結
LeetCode 678. Valid Parenthesis String
題目敘述
函式會輸入一個字串 s,s 只會包含 (、)或是 *,* 可以被任意當作 (、)或是空字串 "" 使用,需要判定輸入的字串 s 是否為 Valid Parenthesis String(VPS),而 VPS 的定義是:
- 所有的
(都有相對應的) - 所有的
)都有相對應的(
若字串 s 為 VPS 就返回 true,反之為 false
解題思路 1:Stack
這題可以用兩種解法來解,第一個先介紹 Leetcode hint 所提示的,使用兩個 stack 來解的方式。
我們可以先分別創建兩個 stack 用來記錄還沒配對的 ( 以及 * 的 index,第一次的迴圈我們只需要判定所有的 ) 是否都有相對應的 (,有的話就從 ( 的 stack 中移除,如果不夠的話就使用 * 的 stack,同樣使用完也從 stack 中移除。
接下來第二個迴圈我們來處理第一個 stack 中剩下未配對的 (,這裡只有當 * 的 index 比 ( 的還要大,我們才能把它當作合法的 ) 來使用
解題步驟
- 創建
(index stack 以及*index stack - 配對所有的
) - 處理未配對的
(
JavaScript 實作
/**
* @param {string} s
* @return {boolean}
*/
var checkValidString = function (s) {
const leftStack = []
const starStack = []
// 第一階段:處理每個 ')'
for (let i = 0; i < s.length; i++) {
if (s[i] === "(") {
leftStack.push(i)
} else if (s[i] === "*") {
starStack.push(i)
} else {
// s[i] === ')'
if (leftStack.length > 0) {
leftStack.pop()
} else if (starStack.length > 0) {
// 把較早出現的 '*' 當成 '('
starStack.pop()
} else {
// 沒有 '(' 或 '*' 可以配對這個 ')'
return false
}
}
}
// 第二階段:用剩餘的 '*' 配對剩餘的 '('
while (leftStack.length > 0 && starStack.length > 0) {
const leftIndex = leftStack.pop()
const starIndex = starStack.pop()
// '*' 必須在 '(' 後面,才能把它當成 ')'
if (leftIndex > starIndex) {
return false
}
}
// 還有未配對的 '(',代表 '*' 不夠
return leftStack.length === 0
}
複雜度
- 時間:
O(n) - 空間:
O(n)
解題思路 2:Min & Max
第二種解法相對較為抽象一點,我們可以先宣告兩個變數 min、max,起始值為 0,並且我們把遇到 ( 的事件視為 +1,遇到 ) 的事件視為 -1,重點在於 *,由於他有可能是 ( 或是 ),所以我們需要同時對 min 去做 -1 以及 max 做 +1,因此 min 與 max 所代表的意義是:如果我們把所有 * 都視為 ( 或是 ) 的話,分數會是多少?接下來需要關注的點有兩個:
Max的值
max < 0,那只有一種可能,)的數量已經超過當下左側(所能負荷的數量了,因此直接返回falsemax > 0,暫時不理他
Min的值
min < 0,在min < 0但是max > 0的情況,表示我們把太多的*當作)來使用,所以我們只需要把min的值拉回成0即可,這個動作的意思是我們把剛剛假設成)的*以(來替代min > 0,如果到了最後迴圈已經走完,但是min > 0的話,表示整個字串中包含了太多的(,因此返回false
JavaScript 實作
/**
* @param {string} s
* @return {boolean}
*/
var checkValidString = function (s) {
let min = 0,
max = 0
for (let i = 0; i < s.length; i++) {
if (s[i] === "(") {
min++
max++
} else if (s[i] === ")") {
min--
max--
} else if (s[i] === "*") {
min--
max++
}
if (max < 0) return false
min = Math.max(min, 0)
}
return min === 0
}
複雜度
- 時間:
O(n) - 空間:
O(1)