数据结构——栈的理解

81 阅读1分钟

栈的特点

  1. 后进先出,js中一般用数组来表示。
  2. 有两种操作入栈push出栈 pop,都是在栈顶进行操作。

LeetCode题目对照解答

  1. 有效括号 20题
给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。

function isValid(str) {
    // 1. 利用栈的特征存储当前匹配的字符串
    // 2. 判断下一个字符串是否与栈中的元素满足题目条件,满足则出栈
    // 3. 返回栈的长度,如果为0则证明刚好一一配对成功。
    let stack = []
    for(let i = 0;i<str.length;i++){
        let st = str[i]
        if(st === '(' || st === '{' || st === '['){
            stack.push(st)
        } else {
            let end = stack.at(-1)
            if(st===')' && end ==='(' || 
               st==='}' && end ==='{' ||
               st===']' && end ==='['
            ){
                stack.pop()
            }
        }
    }
    return stack.length === 0
}
  1. 删除字符串中的所有相邻重复项 1047题
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
输入:"abbaca"
输出:"ca"
1. 先取出之前栈中的元素,同时出栈, stack.pop()
2. 如果之前的元素和当前的元素不相等,则把删除的元素以及当前元素进栈
3. 返回栈中的元素
function removeDuplicates(s){
    let stack = [] 
    for(let v of s){
        let prev = stack.pop()
        if(prev !== v){ 
            stack.push(prev)
            stack.push(v)
        }
    }
    return stack.join('')
}
  1. 最长有效括号 32题
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
1. 使用栈存放当前下标。
2. 循环当前字符串,遇到 '(' 入栈下标,遇到 ')'出栈
3. 如果栈的长度为空则继续放入当前坐标,否则取出当前位置的最大值,当前坐标减去 栈顶的坐标

function longestValidParentheses(s) {
    let stack = []
    stack.push(-1)
    let maxLen = 0
    for(let i in s){
        if(s[i] === '('){
            stack.push(i)
        } else {
            stack.pop()
            if(stack.length === 0){
                stack.push(i)
            } else {
                maxLen = Math.max(maxLen, i - stack.at(-1))
            }
        }
    }
    return maxLen
}
  1. 简化路径 71题
始终以斜杠 '/' 开头。
两个目录名之间必须只有一个斜杠 '/' 。
最后一个目录名(如果存在)不能 以 '/' 结尾。
此外,路径仅包含从根目录到目标文件或目录的路径上的目录(即,不含 '.' 或 '..')
输入: path = "/home/"
输出: "/home"
解释: 注意,最后一个目录名后面没有斜杠。 

输入: path = "/home//foo/"
输出: "/home/foo"

输入: path = "/../"
输出: "/"

1. 把字符串按照'/'分割成数组。
2. 利用栈存储符合条件的值, 如果
3. 返回字符串
function simplifyPath(path){
    let result = '/'
    let stack = []
    let arr = path.split('/')
    arr.forEach(value => {
        if(value && value==='..'){
            stack.pop()
        } else if (value && value !=='.'){
            stack.push(value)
        }
    })
    arr.length ? result = '/' + stack.join('/') : '/'
    return result
}

总结

  1. 多理解。
  2. 多练习。
  3. 勤。