- JS中Math内置对象:常用属性Math.PI
Math方法 | 作用 |
---|---|
Math.random() | 随机数 |
Math.ceil() / Math.floor() | 向上/下取整 |
Math.abs() | 绝对值 |
Math.max() / Math.min() | 最大/小值 |
Math.pow() | 求次方 |
Math.sqrt() | 开根号 |
Math.around() | 四舍五入 |
Math.sin() | 正弦 |
Math.cos() | 余弦 |
Math.trunc() | 向零截断 (正数向下,负数向上) |
- 字符串截断方法
1.array.slice(start,end)
2.array.splice(start,deleteCount,item...)
3.string.split(separator,limit)
操作数和操作符的题目,很容易想到使用栈的方法。
完全模拟栈的方式写的题解:(在计算“+”有个小细节需要注意,因为是把操作数出栈之后再入栈的,需要注意a,b的顺序,后出先进)
/**
* @param {string[]} operations
* @return {number}
*/
var calPoints = function(operations) {
list = [];
for (const op of operations) {
if (op === "C"){
list.pop();
} else if ( op === "D"){
t = list.pop();
list.push(t);
list.push(2*t);
} else if (op === "+") {
a = list.pop();
b = list.pop();
list.push(b, a, a+b);
} else {
list.push(parseInt(op)); //注意将字符串转换成int类型
}
}
return list.reduce( (total, val) => total + val ,0);
};
这里是先得出最后记分数组再计算总分,还有个想法就是在记分的同时计算总分。
逆波兰表达式的计算方法是,运算符写在两个操作数之后,可以通过栈的结构保存操作数,当遇到运算符就出栈两个数,需要注意的是减法和除法的先后顺序。
/**
* @param {string[]} tokens
* @return {number}
*/
var evalRPN = function(tokens) {
var stack=[];
for (const c of tokens){
switch(c){
case '+':
a = stack.pop();
b = stack.pop();
stack.push(b+a);
break;
case '-':
a = stack.pop();
b = stack.pop();
stack.push(b-a);
break;
case '*':
a = stack.pop();
b = stack.pop();
stack.push(b*a);
break;
case '/':
a = stack.pop();
b = stack.pop();
stack.push(Math.trunc(b/a)); //向零截断
break;
default:
stack.push(parseInt(c));
}
}
return stack.pop()
};
括号匹配,采用辅助栈的解法。js中的Map对象很好地通过键和值的配对达成匹配的目的,可以把一组括号存入Map对象中,由于has(),get()方法传入的参数是键,而括号匹配时遇到右括号开始判断,所以我们把右括号存为键,左括号存为值。
/**
* @param {string} s
* @return {boolean}
*/
var isValid = function(s) {
var map = new Map();
map.set(')','(');
map.set('}','{');
map.set(']','[');
var stack = [];
for (const c of s){
if (map.has(c)){ //如果是右括号
//判断栈顶有无匹配的左括号
if (stack.pop() !== map.get(c)) return false;
} else {
stack.push(c);
}
}
// 如果栈非空,说明有括号没有匹配上
if (stack.length) return false;
else return true;
};
官解中加入了字符串长度是否是2的整数倍的判断:
const n = s.length;
if (n % 2 === 1) { return false; }
这题写两个循环暴力求解也能通过,但是执行用时7%,显然有更优化的方法。
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {number[]}
*/
var nextLargerNodes = function(head) {
if (!head.next){
return [0];
}
cur = head;
next = head.next;
var res=[];
while (next){
if (next.val > cur.val){
res.push(next.val);
cur = next;
next = next.next;
} else {
let larger = 0;
temp = next;
// 遍历找到下一个更大的节点
while (temp.next !== null){
temp = temp.next;
if (temp.val > cur.val){
larger = temp.val;
break;
}
}
res.push(larger);
cur = next;
next = next.next;
}
}
// 最后一个节点必然没有下一个更大的节点了,所以为0
res.push(0);
return res;
};
由于需要寻找的是下一个更大的节点,那么在遍历链表的途中,没有找到下一个更大节点的一系列节点必定是一个单调递减的数组。利用这一点可以想到"单调栈"
遍历链表的同时维护一个递减的单调栈,每次进入当前节点后,先把栈中能出栈的出栈(栈顶的值<当前节点的值),再把当前节点放入栈中。
需要注意的是,这里更新结果数组需要知道节点对应的序号,所以额外添加idx记录节点的序号,并且以 [cur.val, idx] 的形式保存栈中内容。
var nextLargerNodes = function(head) {
const ans = [];
const stack = [];
let cur = head;
let idx = -1;
while (cur) {
++idx;
ans.push(0);
// 如果栈不为空且栈顶元素小于当前节点的值,则更新结果数组
while (stack.length && stack[stack.length - 1][0] < cur.val) {
ans[stack.pop()[1]] = cur.val;
}
// 当前节点和它对应的序号入栈
stack.push([cur.val, idx]);
cur = cur.next;
}
return ans;
};
对于嵌套问题,栈的结构是很好的解决方法。
本题对于字符串的处理可能造成一些难度,需要对数字、字母、左右方括号分别进行处理:
var decodeString = function(s) {
// 用两个栈来存放当前状态,前者是重复次数,后者是累积字符串
let repetStack=[],resStack=[];
//拼接字符串
let resStr = "";
//表示重复次数
let repet = 0;
// 遍历s
for(let i=0;i<s.length;i++){
let cur = s.charAt(i);
if(cur == '['){
//双双压入栈中,保存当前状态
repetStack.push(repet);
resStack.push(resStr);
//置空,准备下面的累积
repet = 0;
resStr = "";
}else if(cur == ']'){
// 取出当前重复次数栈中的值,也就是当前字符串的重复次数
let count = repetStack.pop();
// 根据重复次数生成重复字符串,赋值给temp,和resStr拼接
let temp = "";
for(let i = 0;i<count;i++){
temp += resStr;
}
// 和前面已经求得的字符串进行拼接
resStr = resStack.pop() + temp;
}else if(cur>='0' && cur<='9'){
// repet累积
repet = repet*10 + (cur-'0');
}else{
//字符累积
resStr += cur;
}
}
return resStr;
};
作者:ityou-o
链接:https://leetcode.cn/problems/decode-string/solution/javascriptban-jie-ti-si-lu-by-ityou-o-mpy0/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。