【算法13天:Day13】第五章栈和队列 LeetCode 逆波兰表达式求值(150)

103 阅读2分钟

题目一:

image.png

解法一:(栈)

image.png

解题思路:这个题就是遇到数字则压栈,遇到运算符,就出栈运算,需要注意的是,‘-’和‘/’这两个运算符,题目的意思是前一个数减去后一个数,而栈出栈的顺序相反,因此遇到‘-’的时候,后一个减去前一个,结果需要乘以-1,遇到‘/’的时候,也是需要前一个除以后一个,这个时候需要将当前元素和前一个元素记录下来,同时,JS中,如果是大于0的小数,是使用Math.floor(),而小于0的小数,使用的是Math.ceil()。最后需要注意的是,输入的是字符数组,遇到数字字符,压栈的时候是需要类型转换的。

var evalRPN = function(tokens) {
    const stack = []
    let cur = pre = null
    for (let char of tokens) {
        switch (char) {
            case '+':
               stack.push(stack.pop() + stack.pop())
               break
            case '-':
               stack.push((stack.pop() - stack.pop()) * -1)
               break
            case '*':
               stack.push(stack.pop() * stack.pop())
               break
            case '/':
               cur = stack.pop()
               pre = stack.pop()
               stack.push(pre / cur > 0 ? Math.floor(pre / cur) : Math.ceil(pre / cur))       
               break
            default:
               stack.push(parseInt(char))
               break
        }
    }
    return stack.pop()
};

总结:for (let char of tokens) 其中char为单个字符,for (let char in tokens)其中char为索引,这也是for..of 和for...in的区别之一。

for in 和 for of 区别

首先,一句话概括:for in是遍历(object)键名,for of是遍历(array)键值。

1、推荐在循环对象属性的时候使用 for...in,在遍历数组的时候的时候使用 for...of 
2for...in 循环出的是 keyfor...of 循环出的是 value 
3、注意,for...of 是 ES6 新引入的特性。修复了 ES5 引入的 for...in 的不足 
4for...of 不能循环普通的对象(如通过构造函数创造的),需要通过和 Object.keys()搭配使用

for in遍历数组的毛病:

1.index索引为字符串型数字,不能直接进行几何运算
2.遍历顺序有可能不是按照实际数组的内部顺序
3.使用for in会遍历数组所有的可枚举属性,包括原型。例如上述的原型方法method和name属性
所以for in更适合遍历对象,不要使用for in遍历数组。

那么除了使用for循环,如何更简单的正确的遍历数组达到我们的期望呢(即不遍历method和name),ES6中的for of更胜一筹。

解法二:(数组模拟)

var evalRPN = function(tokens) {
    const n = tokens.length;
    const stack = new Array(Math.floor((n + 1) / 2)).fill(0);
    let index = -1;
    for (let i = 0; i < n; i++) {
        const token = tokens[i];
        if (token === '+') {
            index--;
            stack[index] += stack[index + 1];
        } else if (token === '-') {
            index--;
            stack[index] -= stack[index + 1];
        } else if (token === '*') {
            index--;
            stack[index] *= stack[index + 1];
        } else if (token === '/') {
            index--;
            stack[index] = stack[index] / stack[index + 1] > 0 ? Math.floor(stack[index] / stack[index + 1]) : Math.ceil(stack[index] / stack[index + 1]);
        } else {
            index++;
            stack[index] = parseInt(token);
        }
    }
    return stack[index];
}; 

解法三:

const SIGN = {
    '*' : (a, b) => a * b,
    '/' : (a, b) => Math.trunc(a / b),
    '+' : (a, b) => a + b,
    '-' : (a, b) => a - b
}
var evalRPN = function(tokens) {
    const stack = [];
    tokens.forEach(item => {
        if (item in SIGN){
            const b = stack.pop();
            const a = stack.pop();
            const res = SIGN[item](a, b);
            stack.push(res);
        }
        else stack.push(Number(item));
    })
    return stack.pop();
};