LeetCode | 20 Valid Parentheses / 堆疊 (Stack)

閱讀時間約 5 分鐘

記錄這一題的原因,在於透過這題可以學到經典資料結構之一 — 堆疊 (stack)

題幹要求是這樣的:

Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.

所以什麼是滿足題目的合格字串呢?

  1. 左括號要有匹配的右括號,如:( )[ ]{ }。
  2. 左括號必須以正確的順序關閉,比如 ({ )} 就是以不正確順序閉合的字串,但是如果是 ({ }) 就是合格的字串。

要分別滿足這兩個條件,其實可以寫兩個 for 迴圈分別來解決:

function isValid(s: string): boolean {
// 三種情況: '{}', '{[]}', '{}[]'
const open = ['(', '[', '{']
const close = [')', ']', '}']

// 評斷用的數字
let count = 0
let count2 = 0

// 當陣列元素只有一個直接為 false
s.length < 2 && false
// 處理 '{[]}' 的情況
for(let i = 0; i < s.length/2; i++){
const index = open.indexOf(s[i])
if(s[s.length - i -1] === close[index]){
count += 1
}
}
// 處理 '{}[]' 的情況
for(let i = 0; i < s.length; i += 2){
const index = open.indexOf(s[i])
if(s[i + 1] === close[index]){
count2 += 1
}
}

// 評估
if(count === s.length/2 || count2 === s.length/2){
return true
}else{
return false
}
};

但是!這是錯的答案,在第 79 個測試 "(([]){})" 中,上面的程式會給出 false 的答案,但預期其實是 true,這就是因為少考慮了綜合第一個與第二個條件的第三條件。

但其實這題的邏輯只要按下面這個思維想,可以發現其實考慮得不用像上面的程式碼那麼複雜:

  1. 遇到左括號,預期會有一個匹配的右括號。
  2. 遇到第二個左括號,要預期當第二個左括號有閉合的右括號後再往後找匹配第一個左括號的右括號。

就是這個第二點,細細品,他這個 "後遇到,先匹配" 的情況是不是跟資料結構之一的堆疊那 "後進先出" 的理念很像呢?

堆疊的概念

堆疊的概念

上圖就是堆疊 LIFO (Last In First Out) 的概念,新存進的資料必須先取出。

現在來把這題結合堆疊的概念來解:

function isValid(s: string): boolean {
const pairs = { '(': ')', '[': ']', '{': '}' }
let stack: string[] = []

if(s.length < 2){
return false
}

for(let i of s){
if(i in pairs){
stack.push(i)
}else{
let lastOpen = stack.pop()
if(pairs[lastOpen] !== i){
return false
}
}
}

return stack.length === 0
};

上面的關鍵點在於 for 迴圈和裡面的 if-else 判別式。當遍歷字串時遇到左括號時就把它推入堆疊中 (if 區塊中做的事);當遇到右括號時 (else 區塊中做的事),就把最新存到堆疊裡的左括號取出來做比對,如果比對錯誤就直接給出 false 回傳。最後,如果堆疊的長度為 0,就表示所有左括號都成功得到匹配,所以返回 true

LeetCode 之路,任重而道遠啊!

avatar-img
18會員
37內容數
這個專題用來存放我在學習網頁開發時的心得及知識。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
Jeremy Ho的沙龍 的其他內容
SQL語法:JOIN 與交易
SQL 基本篇 - CRUD、運算子、內建函式
MySQL 應用到 URL Shortener 上
LeetCode 518. Coin Challenge II / 動態規劃
SQL語法:JOIN 與交易
SQL 基本篇 - CRUD、運算子、內建函式
MySQL 應用到 URL Shortener 上
LeetCode 518. Coin Challenge II / 動態規劃
你可能也想看
Google News 追蹤
Thumbnail
題目敘述 Combination Sum II_Leetcode #40 給定一個整數陣列candidates 和 目標值target。 每個陣列元素只能選擇一次,請問有多少種組合方法,可以使得組合數總和 = target? 請把滿足組合數總和 = target的組合方法以陣列的形式返回答案
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目敘述 題目會給定我們一個輸入陣列nums,要求我們掃描美個陣列元素nums[i],計算除了nums[i]以外的陣列元素連乘積。 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4] Output: [24,12,8,6] nums[0] 以
Thumbnail
題目敘述 題目會給我們一個字串s。 要求我們移除字串中的星號,還有刪除星號左手邊最靠近的第一個字元。 以字串的形式返回輸出答案。 題目的原文敘述 測試範例 Example 1: Input: s = "leet**cod*e" Output: "lecoe" Explanation:
Thumbnail
題目敘述 題目會給定一個輸入字串s和一套編碼規則,要求我們針對字串s進行解碼,並且以字串的形式返回答案。 編碼規則: 數字[字串] -> []內的字串以對應倍數做展開,而且允許巢狀編碼。 例如: 3[a] 解碼完就是 aaa 2[bc] 解碼完就是 bcbc 2[a2[b]] = 2
Thumbnail
題目敘述 題目會給定我們兩個輸入字串word1, word2,要求我們依照word1,word2,word1,word2, ... 交叉前進的方式,合併兩個字串,作為輸出。 題目的原文敘述 測試範例 Example 1: Input: word1 = "abc", word2 = "pq
Thumbnail
題目敘述 題目會給我們兩個輸入,字串s和字串t,要求我們判定s是否為t的子序列(Subsequence)? 題目的原文敘述 測試範例 Example 1: Input: s = "abc", t = "ahbgdc" Output: true Example 2: Input:
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,和一個指定的k值。 請問,在輸入陣列nums中,有幾個子陣列的元素總合恰好為k ? 例如: nums = [1,2,3], k = 3 則有兩個子陣列的元素總合為3,分別是[1,2] 和 [3] 如果是第一次聽到或接觸前綴和prefix的同學
Thumbnail
題目敘述 題目會給定一個整數陣列arr,要求我們判斷是否每個元素的出現次數都不同? 題目的原文敘述 測試範例 Example 1: Input: arr = [1,2,2,1,1,3] Output: true Explanation: The value 1 has 3 occurre
Thumbnail
題目敘述 題目會給定我們兩個字串word1 和 word2。 允許我們不限制次數進行下列兩種操作: 任意調換其中兩個字元的位置。 把字串中的某個字元全部置換成另一個字元,同時把另一個字元同時置換成某個字元。(例如把字串中原本的a都換成b,把原本的b都換成a) 問我們能不能通過上述兩項操作,
Thumbnail
題目敘述 Combination Sum II_Leetcode #40 給定一個整數陣列candidates 和 目標值target。 每個陣列元素只能選擇一次,請問有多少種組合方法,可以使得組合數總和 = target? 請把滿足組合數總和 = target的組合方法以陣列的形式返回答案
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目敘述 題目會給定我們一個輸入陣列nums,要求我們掃描美個陣列元素nums[i],計算除了nums[i]以外的陣列元素連乘積。 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4] Output: [24,12,8,6] nums[0] 以
Thumbnail
題目敘述 題目會給我們一個字串s。 要求我們移除字串中的星號,還有刪除星號左手邊最靠近的第一個字元。 以字串的形式返回輸出答案。 題目的原文敘述 測試範例 Example 1: Input: s = "leet**cod*e" Output: "lecoe" Explanation:
Thumbnail
題目敘述 題目會給定一個輸入字串s和一套編碼規則,要求我們針對字串s進行解碼,並且以字串的形式返回答案。 編碼規則: 數字[字串] -> []內的字串以對應倍數做展開,而且允許巢狀編碼。 例如: 3[a] 解碼完就是 aaa 2[bc] 解碼完就是 bcbc 2[a2[b]] = 2
Thumbnail
題目敘述 題目會給定我們兩個輸入字串word1, word2,要求我們依照word1,word2,word1,word2, ... 交叉前進的方式,合併兩個字串,作為輸出。 題目的原文敘述 測試範例 Example 1: Input: word1 = "abc", word2 = "pq
Thumbnail
題目敘述 題目會給我們兩個輸入,字串s和字串t,要求我們判定s是否為t的子序列(Subsequence)? 題目的原文敘述 測試範例 Example 1: Input: s = "abc", t = "ahbgdc" Output: true Example 2: Input:
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,和一個指定的k值。 請問,在輸入陣列nums中,有幾個子陣列的元素總合恰好為k ? 例如: nums = [1,2,3], k = 3 則有兩個子陣列的元素總合為3,分別是[1,2] 和 [3] 如果是第一次聽到或接觸前綴和prefix的同學
Thumbnail
題目敘述 題目會給定一個整數陣列arr,要求我們判斷是否每個元素的出現次數都不同? 題目的原文敘述 測試範例 Example 1: Input: arr = [1,2,2,1,1,3] Output: true Explanation: The value 1 has 3 occurre
Thumbnail
題目敘述 題目會給定我們兩個字串word1 和 word2。 允許我們不限制次數進行下列兩種操作: 任意調換其中兩個字元的位置。 把字串中的某個字元全部置換成另一個字元,同時把另一個字元同時置換成某個字元。(例如把字串中原本的a都換成b,把原本的b都換成a) 問我們能不能通過上述兩項操作,