二叉树的后序遍历
问题描述: 给定一个二叉树,返回它的 后序 遍历。(by leetcode 145)
示例:
输入: [1,null,2,3]
1
\
2
/
3
输出: [3,2,1]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
思路:
方法一:递归
方法二:迭代
1.遍历树节点,向压入栈中,一直找到栈顶元素的左子树,直到某一节点没有左子树,弹出该节点,再找该节点的右子树,
2.对右子树重复1操作,若没有右子树,直接返回当前节点,否则压入栈中。
3.当本右子树遍历完成,则说明本节点左右子树都已经完成,返回该节点,继续查找栈顶元素,直到栈为空。
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[]}
*/
方法一:递归 左右中
var postorderTraversal = function(root) {
if(root==null) return [];
let res=[];
function rear(root){
if(root==null) return;
rear(root.left)
rear(root.right)
res.push(root.val)
}
rear(root);
return res;
};
方法二:迭代
var postorderTraversal = function(root) {
if(root==null) return [];
let res=[];
let stk=[];
let prev=null;
while(root!==null||stk.length){
while(root){
stk.push(root);
root=root.left
}
root=stk[stk.length-1];
stk.pop();
if(root.right==null||root.right==prev){
res.push(root.val);
prev=root;
root=null;
}else{
stk.push(root)
root=root.right;
}
}
return res
};
验证二叉树的前序序列化
问题描述: 序列化二叉树的一种方法是使用前序遍历。当我们遇到一个非空节点时,我们可以记录下这个节点的值。如果它是一个空节点,我们可以使用一个标记值记录,例如 #。(by leetcode 331)
_9_
/ \
3 2
/ \ / \
4 1 # 6
/ \ / \ / \
# # # # # #
例如,上面的二叉树可以被序列化为字符串 "9,3,4,#,#,1,#,#,2,#,6,#,#",其中 # 代表一个空节点。
给定一串以逗号分隔的序列,验证它是否是正确的二叉树的前序序列化。编写一个在不重构树的条件下的可行算法。
每个以逗号分隔的字符或为一个整数或为一个表示 null 指针的 '#' 。
你可以认为输入格式总是有效的,例如它永远不会包含两个连续的逗号,比如 "1,,3" 。
示例 1:
输入: "9,3,4,#,#,1,#,#,2,#,6,#,#"
输出: true
思路:
方法一:通过遍历数组,向栈中压入,遇到x##,则变为#,当遍历完最后一个值,且对栈中元素处理完。如果是二叉树,则最后应该返回只有一个#元素的栈。
方法二:通过度来判断 二叉树的话,出度-入度=0;
每个节点-1(入度),当遇到#,说明是子节点,那么+2(出度-入度=2),最后看diff的值是不是0
/**
* @param {string} preorder
* @return {boolean}
*/
方法一:栈 合并“x,#,# 为 #”
var isValidSerialization = function(preorder) {
let arr=preorder.split(",");
let stk=[];
for(let i=0;i<arr.length;i++){
stk.push(arr[i])
while(stk.length>2&&stk[stk.length-2]==="#"&&stk[stk.length-1]==="#"&&stk[stk.length-3]!=="#"){
stk.pop();
stk.pop();
stk[stk.length-1]="#"
}
}
return stk.length===1&&stk[0]==="#"
};
方法二:度 出度-入度
var isValidSerialization = function(preorder) {
let arr=preorder.split(",");
let stk=[];
let diff=1;
for(let i=0;i<arr.length;i++){
diff--;
if(diff<0)return false;
if(arr[i]!=="#")diff+=2;
}
return diff===0
};
基本计算器 II
问题描述: 给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。(by leetcode227)
整数除法仅保留整数部分。
示例 1:
输入:s = "3+2*2"
输出:7
思路: 遇到数字则统计数字,遇到符号,则判断上一个符号,用栈顶元素(符号运算)当前统计的数字,并往栈中放入当前计算值,注意:最后一个元素,应该是要参与运算的。
/**
* @param {string} s
* @return {number}
*/
var calculate = function(s) {
let stk=[];
let arr= s.trim();
let pre=0;
let way="+"
for(let i=0;i<arr.length;i++){
if(!isNaN(Number(arr[i]))&& arr[i] !== ' '){
pre=pre*10+arr[i].charCodeAt()-'0'.charCodeAt()
}
if(isNaN(Number(arr[i]))||i===arr.length-1){
switch(way){
case "+":
stk.push(pre)
break;
case "-":
stk.push(-pre)
break;
case "*":
stk.push(stk.pop()*pre)
break;
default:
stk.push(stk.pop()/pre|0)
}
pre=0;
way=arr[i]
}
}
let res=0
while(stk.length){
res+=stk[stk.length-1]
stk.pop()
}
return res;
};
表现良好的最长时间段
问题描述:
给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数。
我们认为当员工一天中的工作小时数大于 8 小时的时候,那么这一天就是「劳累的一天」。
所谓「表现良好的时间段」,意味在这段时间内,「劳累的天数」是严格 大于「不劳累的天数」。
请你返回「表现良好时间段」的最大长度。(by leetcode 1124)
示例 1:
输入:hours = [9,9,6,0,6,6,9]
输出:3
解释:最长的表现良好时间段是 [9,9,6]。
思路: 看注释
/**
* @param {number[]} hours
* @return {number}
*/
var longestWPI = function(hours) {
for(let i=1;i<=arr.length;i++){
sum.push(sum[i-1]+arr[i-1])
}
let stack=[0]
for(let i=1;i<sum.length;i++){
if(sum[stack.length-1]>sum[i]){
stack.push(i)
}
}
let res=0;
将每一个递减时间点跟整条增长情况折线图对比,
while(stack.length){
for(let i=sum.length;i>0;i--){
if(sum[i]>sum[stack[stack.length-1]]){
res=Math.max(i-stack[stack.length-1],res)
}
}
stack.pop()
}
return res
};
/**
* @param {number[]} hours
* @return {number}
*/
var longestWPI = function(hours) {
let arr=[];、
//1.列出时间线上劳动时间表现。
for(let i=0;i<hours.length;i++){
if(hours[i]>8){
arr.push(1)
}
else{
arr.push(-1)
}
}
let sum=[0];
//从前完后看增长情况折线图。
for(let i=1;i<=arr.length;i++){
sum.push(sum[i-1]+arr[i-1])
}
console.log(sum)
let stack=[0];
// 找到绝对的递减时间点
for(let i=1;i<sum.length;i++){
if(sum[i]<sum[stack.length-1]){
stack.push(i)
}
}
console.log(stack)
let res=0;
// 针对每个绝对递减时间点,循环增长数组,有大于递减时间点的,说明这一段上面有效时间较多
while(stack.length){
for(let i=sum.length-1;i>=0;i--){
if(sum[i]>sum[stack.length-1]){
res=Math.max(i-stack.length+1,res)
}
}
stack.pop()
}
return res
};