算法刷题——栈、队列

79 阅读1分钟

20 有效的括号

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

有效字符串需满足:

左括号必须用相同类型的右括号闭合。

左括号必须以正确的顺序闭合。

注意空字符串可被认为是有效字符串。

输入: "()"
输出: true
输入: "()[]{}"
输出: true
输入: "(]"
输出: false

思路解析

遇到左括号入栈,遇到右括号出栈顶,如果匹配就继续,否则就不匹配。

/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function(s) {
    let stack = [];
    for(let i = 0; i < s.length; i++){
        if(s[i] === '(' || s[i] === '[' || s[i] === '{'){
            stack.push(s[i]);
        }
        else{
            if(stack.length === 0)
                return false;
            let temp = stack.pop();
            switch(temp){
                case '(':
                    if(s[i] !== ')')
                        return false;
                    break;
                case '[':
                    if(s[i] !== ']')
                        return false;
                    break;
                case '{':
                    if(s[i] !== '}')
                        return false;
                    break;
            }
        }
    }
    if(stack.length !== 0)
        return false;
    return true;
};

150 逆波兰表达式求值

根据逆波兰表示法,求表达式的值。 有效的运算符包括 +, -, * , / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

说明: 整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

输入: ["2", "1", "+", "3", "*"]
输出: 9
解释: ((2 + 1) * 3) = 9
输入: ["4", "13", "5", "/", "+"]
输出: 6
解释: (4 + (13 / 5)) = 6

leetcode-cn.com/problems/ev…

解题思路

遇到数就入栈,遇到运算符就出栈,这里的运算符都是双目运算符所以弹出两个,计算后在入栈,最后栈中只剩下结果。

parseInt()/parseFloat([val,[进制]])的作用

let str = '12.5px'
parseInt(str) // 12
parseFloat(str)// 12.5
parseFloat(true)// NaN
isNaN()如果当前为数字类型,则返回 false,否则返回 true
/**
 * @param {string[]} tokens
 * @return {number}
 */
var evalRPN = function(tokens) {
    let stack = [];
    for(let i = 0; i < tokens.length; i++){
        let num = parseInt(tokens[i]);
        if(!isNaN(num)){
            stack.push(num);
        }
        else{
            let num1 = stack.pop();
            let num2 = stack.pop();
            switch(tokens[i]){
                case '+':
                        stack.push(num2 + num1);
                        break;
                case '-':
                        stack.push(num2 - num1);
                        break;
                case '*':
                        stack.push(num2 * num1);
                        break;
                case '/':
                        stack.push(parseInt( num2 / num1 ));
                        break;
            }
        }
    }
    return stack.pop();
};

71.简化路径

以 Unix 风格给出一个文件的绝对路径,你需要简化它。或者换句话说,将其转换为规范路径。

在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。更多信息请参阅:Linux / Unix 中的绝对路径 vs 相对路径

请注意,返回的规范路径必须始终以斜杠 / 开头,并且两个目录名之间必须只有一个斜杠 /。最后一个目录名(如果存在)不能以 / 结尾。此外,规范路径必须是表示绝对路径的最短字符串。

输入:"/home/"
输出:"/home"
解释:注意,最后一个目录名后面没有斜杠。
输入:"/../"
输出:"/"
解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级。
输入:"/home//foo/"
输出:"/home/foo"
解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
输入:"/a/./b/../../c/"
输出:"/c"
输入:"/a/../../b/../c//.//"
输出:"/c"
输入:"/a//b////c/d//././/.."
输出:"/a/b/c"

leetcode-cn.com/problems/si…

解题思路

1.用 / 来分割路径字符串,然后不停的把分割后的有效值 push 到栈中。

2.有效值是非 '..'、'.'、'' 这些特殊值以外的值。

3.遇到 .. 字符,说明要回退一级目录,把栈中弹出一个值即可。

4.注意最后的/不要加

/**
 * @param {string} path
 * @return {string}
 */
var simplifyPath = function(path) {
    let newPath = path.split('/');//根据斜杠分割字符串
    let stack = [];
    for(let i = 0; i < newPath.length; i++){
        if(newPath[i] ==='..'){ //要返回上一级就pop出上一个压入的
            stack.pop();
        }else if(newPath [i] !== '.' && newPath[i] !== ''){
            stack.push(newPath[i]);
        }
    }
    let out = "/";
    for(let i = 0; i < stack.length; i++){
        out += stack[i];
        if(i !== stack.length - 1)//最后一个没有斜杠
            out += '/';
    }
    return out;

};

239 滑动窗口的最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值。

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
1 [3  -1  -3] 5  3  6  7       3
1  3 [-1  -3  5] 3  6  7       5
1  3  -1 [-3  5  3] 6  7       5
1  3  -1  -3 [5  3  6] 7       6
1  3  -1  -3  5 [3  6  7]      7

链接:leetcode-cn.com/problems/sl…

解题思路2:

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
let maxSlidingWindow = function(nums, k) {
    let left = 0;
    let right = 0;
    let queue = [];
    let min = Infinity;
    while(right < k){
        if(nums[right] > min){
            while(queue.length !== 0 && queue[queue.length - 1] < nums[right]){
                queue.pop();
            }
        }
        queue.push(nums[right]);
        min = nums[right];
        right++;
    }
    let res = [queue[0]];
    while(right < nums.length){
      if(queue[0] === nums[left]){
          queue.shift();
      } 
      left++;

      if(nums[right] > min){
          while(queue.length!==0 && queue[queue.length - 1] < nums[right]){
              queue.pop();
          }
      }
      queue.push(nums[right]);
      min = nums[right];
      res.push(queue[0]);
      right++; 
    }
    return res;
};