有效的括号
給定一個隻包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字元串 s ,判斷字元串是否有效。
有效字元串需滿足:
左括号必須用相同類型的右括号閉合。
左括号必須以正确的順序閉合。
示例 1:
輸入:s = “()”
輸出:true
示例 2:
輸入:s = “()[]{}”
輸出:true
示例 3:
輸入:s = “(]”
輸出:false
示例 4:
輸入:s = “([)]”
輸出:false
示例 5:
輸入:s = “{[]}”
輸出:true
提示:
1 <= s.length <= 104 s 僅由括号 ‘()[]{}’ 組成
leedtcode 連結
1.分析
根據題意我們可以得出:
1.有效的字元串長度一定是偶數,否則無效
2.右括号前邊必須是對應的左括号才有效,否則無效
3.我們可以使用棧來看資料是否對應,比如,遇左括号就壓入棧
4.如遇右括号,彈出棧頂,兩者對應,則抵消
5.最後棧中還有資料,證明沒有全部抵消,字元串無效
2.題解
下面我們使用兩個方法來完成這道題
解法1 - 使用 es6的 map
var isValid = function(s) {
let l = s.length
if (l % 2 !== 0 ) { return false } // 1.字元串長度不是偶數直接傳回 false
let map = new Map([['}', '{'], [')', '('], [']', '[']])
// 2.使用 map 将括号映射成如下鍵值對(因為我們通過右括号判斷左括号):
// Map(3) {')' => '(', ']' => '[', '}' => '{'}
let stack = []
for (let i of s) { // 循環周遊目前字串
if (map.get(i)) { // 3.判斷有無目前鍵對應的值,因為我們是通過右括号判斷左括号,但字串順序是從左到右的,是以前幾輪判斷會走 else
if (stack[stack.length - 1] === map.get(i)) { // 4.判斷右括号時,找對應括号需從數組倒序比較,即從最後一個元素依次開始
stack.pop() // 4.如果相等即彈出
} else {
return false // 4.否則傳回false開始下一輪循環
}
} else {
stack.push(i) // 3.如字串'[({})]'前三輪會将'[({'寫入數組
}
}
return !stack.length;
}
走過的坑:
1.map 用法
map 生成鍵值對,和數組的轉換
此例中,要想生成 {’)’ => ‘(’, ‘]’ => ‘[’, ‘}’ => ‘{’}的映射關系,需要在 new Map()中嵌套數組,加一個’[ ]’
2.for in 和 for of 差別
for…of适用周遊數/數組對象/字元串/map/set等擁有疊代器對象的集合.但是不能周遊對象, 因為沒有疊代器對象.與forEach()不同的是,它可以正确響應break、continue和return語句,for-of循環不支援普通對象,不建議使用 for-in 屬性周遊數組等,因為,for in周遊的是數組的索引(即鍵名),而for of周遊的是數組元素值。
如果你想疊代一個對象的屬性,你可以用for-in循環(這也是它的本職工作)或内建的Object.keys()方法:
Array pop()方法
pop() 方法移除數組的最後一個元素,并傳回該元素。
解法2 - switch case 或者 if 按條件判斷
把左括号全部推入棧中,到右括号時依次從棧頂彈出比較
let isValid = function(s) {
let l = s.length;
if (l % 2 !== 0) { return false };
let stack = []
for (let i of s) {
switch (i) {
case '{':
case '[':
case '(':
stack.push(i);
break;
case '}':
if(stack.pop() !== '{') return false;
break;
case ']':
if(stack.pop() !== '[') return false;
break;
case ')':
if(stack.pop() !== '(') return false;
break;
}
}
return !stack.length;
}