给定只包含括号的字符串,判断括号是否匹配
/**
* @param {string} s
* @return {boolean}
*/
//声明了栈数据结构及其方法
class Stack{
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
return this.items.pop();
}
isEmpty() {
return !this.items.length;
}
}
//新建栈的实例用来保存遍历过的左括号,遍历一个左括号就入栈一个对应的右括号,遇到右括号就与栈顶元素比较;
//字符串length为单数,false;
//最后遍历完所有字符串元素,如果栈不为空,false。
var isValid = function(s) {
const myStack = new Stack()
const lenS = s.length;
if(lenS % 2 !== 0) return false;
for(let i = 0; i < lenS; i++) {
if(s[i] == '(') {
myStack.push(')');
} else if(s[i] == '{') {
myStack.push('}');
} else if(s[i] == '[') {
myStack.push(']');
} else if(myStack.isEmpty() || myStack.pop() !== s[i]) {
return false;
}
}
return myStack.isEmpty();
};
- 其实可以不用声明堆栈的类别,直接定义一个数组保存堆栈元素就可以,以下两题就是直接使用数组;
- 本题是进行括号的匹配,那么字符串的长度肯定是双数,单数就直接false;
- 栈是如何应用上的?括号要匹配,左括号肯定在右括号前。那么遍历字符串,遇到左括号,就将一个对应的右括号压入栈中,遇到右括号就从栈里弹出元素与它对比,不相等证明不匹配。直到遍历完整个字符串;
- 遍历完整个字符串时,如果栈中还有元素,证明有左括号落单,false;栈为空是我们想看到的。
删除字符串中所有的相邻重复项
/**
* @param {string} s
* @return {string}
*/
var removeDuplicates = function(s) {
const stack = [];
stack.push(s[0]);
const lenS = s.length;
for(let i = 1; i < lenS; i++) {
//当前元素不等于栈顶元素,继续入栈.相等就弹出
if(stack == [] || s[i] !== stack[stack.length - 1]) {
stack.push(s[i]);
} else {
stack.pop();
}
}
//数组转string
return stack.join('');
};
- 这种比较相邻元素的问题,用堆栈处理简直完美;
- 首先将字符串中的第一个元素压入栈中,然后遍历字符串,将字符串元素与栈顶元素比较,在进行相应的操作;
- 值得注意的一点是,要考虑中途出现空栈的问题,这个时候length = 0,取栈顶元素此时会返回undefined。那么遇到空栈就直接将当前元素压入栈顶即可(跳过取栈顶元素这步)。
逆波兰表达式求值
/**
* @param {string[]} tokens
* @return {number}
*/
var evalRPN = function(tokens) {
stack = [];
for(let i = 0; i < tokens.length; i++){
let c = tokens[i];
if(!isNaN(c)){
stack.push(c);
} else if(c == "+") {
let num1 = +stack.pop();
let num2 = +stack.pop();
stack.push(num1 + num2);
// console.log('JIAHAO:'+stack);
}else if(c == "-") {
let num1 = +stack.pop();
let num2 = +stack.pop();
stack.push(num2 - num1);
// console.log(stack);
}else if(c == "/") {
let num1 = +stack.pop();
let num2 = +stack.pop();
//注意除法运算时,根据商的正负进行取上限取下限操作
if(num2 / num1 > 0) {
stack.push(Math.floor(num2 / num1));
} else{
stack.push(Math.ceil(num2 / num1));
}
}else {
let num1 = +stack.pop();
let num2 = +stack.pop();
stack.push(num2 * num1);
// console.log("➗"+stack);
}
}
// console.log(stack);
return stack[0];
};
- 遍历字符串,遇到数字就直接进栈,遇到运算符就弹出两个元素进行相应元素,然后再把结果压入栈中;
- 值得注意的是,题目给的是字符串数组,那么把数值元素取出来之后是string类型,不能直接进行想要的算数运算,在数值前直接加“+“即可转换为number;
- 还有就是进行除法运算时,根据结果的正负选择是取上限还是取下限,否则测试用例总卡在15/21.例如计算(6÷(-132)),我们希望得到的结果是0,而不是-1。(题目说了除法向零截断)。
心得体会
坚持就是胜利!耶!每一天都元气满满!