二叉树层次遍历(leetcode102)
https://leetcode-cn.com/problems/binary-tree-level-order-traversal/
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number[][]}
*/
var levelOrder = function(root) {
if(!root){
return [];
}
let result = [];
helper(root,0,result);
return result;
}
var helper = function(node,level,result){
if(!node){
return;
}
if(!result[level]){
result[level]=[node.val]
}else{
result[level].push(node.val)
}
helper(node.left,level+1,result);
helper(node.right,level+1,result);
}
// 队列
// var levelOrder = function(root) {
// if(!root){
// return []
// }
// let queue = [root];
// let result = [];
// let level = 0;
// while(queue.length !== 0){
// let len = queue.length;
// for(let i=0;i<len;i++){
// let node = queue.shift();
// if(!result[level]){
// result[level]=[node.val]
// }else{
// result[level].push(node.val)
// }
// if(node.left)queue.push(node.left);
// if(node.right)queue.push(node.right);
// }
// level++;
// }
// return result
// };
二叉树前序遍历(leetcode144)
/**
* @param {TreeNode} root
* @return {number[]}
*/
// 非递归解法-栈
var preorderTraversal = function(root) {
if(!root){
return [];
}
let stack = [root];
let result = [];
while(stack.length){
let node = stack.pop();
result.push(node.val);
if(node.right){
stack.push(node.right);
}
if(node.left){
stack.push(node.left);
}
}
return result;
};
二叉树后序遍历(leetcode145)
//非递归实现
/**
* @param {TreeNode} root
* @return {number[]}
*/
var postorderTraversal = function(root) {
if(!root){
return [];
}
let result = [];
let stack = [root];
while(stack.length){
let node = stack.pop();
result.unshift(node.val);
if(node.left){
stack.push(node.left);
}
if(node.right){
stack.push(node.right);
}
}
return result;
};
//递归实现
/**
* @param {TreeNode} root
* @return {number[]}
*/
var postorderTraversal = function(root) {
if(!root){
return [];
}
let result = [];
traverse(root,result);
return result;
};
var traverse = function(node, result){
if(node.left){
traverse(node.left, result);
}
if(node.right){
traverse(node.right, result);
}
result.push(node.val);
return;
}
二叉树中序遍历(leetcode94)
非递归解法
/**
* @param {TreeNode} root
* @return {number[]}
*/
var inorderTraversal = function(root) {
if(!root){
return [];
}
let stack = [];
let result = [];
let curr = root;
while(stack.length || curr!==null ){
// 把左子节点都入栈
while(curr !== null){
stack.push(curr);
curr = curr.left;
}
// 弹出最左的节点
let top = stack.pop();
result.push(top.val);
// 如果有右子树,遍历右子树
curr = top.right;
}
return result;
};
二叉树路径总和(leetcode113)
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {number} sum
* @return {number[][]}
*/
//递归解法
var pathSum = function(root, sum) {
var result = [];
var traverse = function(node,total,arr){
if(!node){
return;
}
let path = [...arr,node.val];
if(node.left===null&&node.right===null&&total+node.val===sum) {
result.push(path);
return;
}
traverse(node.left,total+node.val,path);
traverse(node.right,total+node.val,path);
}
traverse(root,0,[]);
return result;
};
//栈解法
var hasPathSum = function(root, sum) {
let stack = [];
let result = false;
if(root){
stack.push([root,sum])
}
while(stack.length){
let item = stack.pop();
let node = item[0],remain = item[1];
if(node.left===null && node.right===null && remain-node.val===0){
result = true;
break;
}
if(node.left){
stack.push([node.left,remain-node.val]);
}
if(node.right){
stack.push([node.right,remain-node.val]);
}
}
return result;
};
二叉树Z字型遍历(leetcode103)
//队列方法
var zigzagLevelOrder = function(root) {
let queue = [];
let result = [];
if(root){
queue.push([root,0]);
}
while(queue.length){
let item = queue.shift();
let node = item[0],level=item[1];
if(result[level]){
if(level % 2 === 0){
result[level].push(node.val);
}else{
result[level].unshift(node.val);
}
}else{
result[level] = [node.val];
}
if(node.left){queue.push([node.left,level+1]);}
if(node.right){queue.push([node.right,level+1]);}
}
return result;
};
从前序和中序遍历构造二叉树(leetcode105)
/**
* @param {number[]} preorder
* @param {number[]} inorder
* @return {TreeNode}
*/
var buildTree = function(preorder, inorder) {
var traverse = function(preorder, inorder){
if(!preorder.length || !inorder.length){
return null;
}
let t = preorder[0];
let node = new TreeNode(t);
let midIndex = inorder.indexOf(t);
node.left = traverse(preorder.slice(1,midIndex+1),inorder.slice(0,midIndex));
node.right = traverse(preorder.slice(midIndex+1),inorder.slice(midIndex+1));
return node;
}
return traverse(preorder,inorder);
};
有序链表转换二叉搜索树(LeetCode 109)
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {ListNode} head
* @return {TreeNode}
*/
var sortedListToBST = function(head) {
return createTree(head);
};
// 双指针解法
var createTree = function(head){
// console.log(1,head);
if(!head)return null;
if(!head.next){
return new TreeNode(head.val);
}
// p1指向中间节点的前一个节点,p2指向尾结点
let p1 = head,p2 = head;
let start = false;
while(p2.next && p2.next.next){
p2 = p2.next.next;
if(!start){
start = true;
continue;
}else{
p1 = p1.next;
}
}
// console.log('p1',p1);
// console.log("=====")
let node = new TreeNode(p1.next.val);
let newH = p1.next;
p1.next=null;
node.left = head?createTree(head):null;
node.right = newH.next?createTree(newH.next):null;
return node;
}
判断二叉搜索树是否合理(leetcode98)
中序遍历递归解法
/**
* @param {TreeNode} root
* @return {boolean}
*/
var isValidBST = function(root) {
if(!root){
return true;
}
let result = true;
let preValue = null;
var traverse = function(node){
if(node.left&&result){
traverse(node.left);
}
if(preValue!==null){
if(preValue>=node.val)result = false;
}
preValue = node.val;
if(node.right&&result){
traverse(node.right);
}
}
traverse(root)
return result;
};
官方解法
左右两个子树都是BST这个树才是BST,当前节点要满足在(lower,upper)
区间内
var isValidBST = function(root) {
if(!root){
return true;
}
return helper(root,-Infinity,Infinity);
};
var helper = function(node,lower,upper){
if(!node)return true;
if(node.val<=lower || node.val>=upper){
return false;
}
return helper(node.left,lower,node.val) && helper(node.right,node.val,upper)
}
二叉搜索树中第K小的元素
一般BST遍历==》中序遍历
/**
* @param {TreeNode} root
* @param {number} k
* @return {number}
*/
var kthSmallest = function(root, k) {
let stack = [];
let curr = root;
let count = 0;
let result = null;
while(stack.length || curr!==null){
while(curr!==null){
stack.push(curr);
curr = curr.left;
}
let top = stack.pop();
count++;
if(count === k){
result = top.val;
break;
}
curr = top.right;
}
return result;
};
二叉树两个节点最近祖先(leetcode236)
//参考大佬的做法
/**
* @param {TreeNode} root
* @param {TreeNode} p
* @param {TreeNode} q
* @return {TreeNode}
*/
var lowestCommonAncestor = function(root, p, q) {
//递归终止条件:节点为空,节点等于p或q
if(!root || root === p || root === q)return root;
//遍历左右子树
let left = lowestCommonAncestor(root.left,p,q);
let right = lowestCommonAncestor(root.right,p,q);
//如果p和q在不同的子树,返回当前节点
if(left && right) return root;
//如果p和q在同一个子树,返回那个子树的节点
return left?left:right;
};
全排列
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
DFS+回溯算法
/**
* @param {number[]} nums
* @return {number[][]}
*/
var permute = function(nums) {
let result = [];
let len = nums.length;
if(!len){
return [];
}
let path = [];
let used = [];
dfs(nums,len,0,path,used,result);
return result
};
var dfs = function(nums,len,depth,path,used,result){
if(depth === len){
result.push(path.slice());
return;
}
for(let i=0;i<len;i++){
if(used[i]){
continue;
}
path.push(nums[i]);
used[i] = true;
dfs(nums,len,depth+1,path,used,result);
path.pop();
used[i] = false;
}
}
反转链表
/**
* @param {ListNode} head
* @return {ListNode}
*/
// 递归解法
var reverseList = function(head) {
if(!head)return null;
if(head.next === null)return head;
let last = reverseList(head.next);
head.next.next = head;
head.next = null;
return last;
};
// 迭代解法
var reverseList = function(head) {
if(!head)return null;
let pre = head, curr = head.next, newHead=head;
while(curr!==null){
newHead = curr;
curr = curr.next;
newHead.next = pre;
if(pre===head)pre.next = null;
pre = newHead;
}
return newHead;
};
对称二叉树(LeetCode101)
/**
* @param {TreeNode} root
* @return {boolean}
*/
// 非递归解法
var isSymmetric = function(root) {
if(!root)return true;
let queue = [root.left,root.right];
while(queue.length!==0){
let v1 = queue.shift();
let v2 = queue.shift();
if(v1 === null && v2 === null){
continue;
}
if(v1 ===null || v2===null){
return false;
}
if(v1.val !== v2.val){
return false;
}
queue.push(v1.left);
queue.push(v2.right);
queue.push(v1.right);
queue.push(v2.left);
}
return true;
};
// 递归解法
// var isSymmetric = function(root) {
// if(!root)return true;
// return isMirror(root.left,root.right)
// };
// var isMirror = function(p,q){
// if(p === null && q === null)return true;
// if(p === null || q === null)return false;
// return p.val === q.val && isMirror(p.left,q.right)
// && isMirror(p.right,q.left);
// }
平衡二叉树(LeetCode110)
/**
* @param {TreeNode} root
* @return {boolean}
*/
// 递归解法
var isBalanced = function(root) {
if(!root)return -1;
return Math.abs(depth(root.left)-depth(root.right))<2 && isBalanced(root.left) && isBalanced(root.right);
};
var depth = function(root){
if(!root)return 0;
return Math.max(depth(root.left),depth(root.right))+1;
}
二叉树的最小深度(LeetCode 111)
/**
* 递归解法
* 当前节点的最小深度 = 左右子节点最小深度+1
*/
var minDepth = function(root){
if(!root)return 0;
if(root.left === null && root.right === null){
return 1;
}
let min = Infinity;
if(root.left)min = Math.min(minDepth(root.left),min);
if(root.right)min = Math.min(minDepth(root.right),min);
return min+1;
}
/**
* 层次遍历 遇到的第一个叶子节点所在深度就是最小深度
*/
var minDepth = function(root) {
if(!root)return 0;
let queue = [root];
let level = 1;
while(queue.length){
let len = queue.length;
for(let i = 0;i<len;i++){
let node = queue.shift();
if(node.left === null && node.right === null){
return level;
}
if(node.left)queue.push(node.left);
if(node.right)queue.push(node.right);
}
level++;
}
};
二叉树路径总和(LeetCode 112)
给定二叉树和目标值,是否存在一条路径和为目标值
/**
* @param {TreeNode} root
* @param {number} sum
* @return {boolean}
*/
/**
* 栈解法
* 栈里存储节点和剩余的值
*/
var hasPathSum = function(root, sum) {
let stack = [];
let result = false;
if(root){
stack.push([root,sum])
}
while(stack.length){
let item = stack.pop();
let node = item[0],remain = item[1];
if(node.left===null && node.right===null && remain-node.val===0){
result = true;
break;
}
if(node.left){
stack.push([node.left,remain-node.val]);
}
if(node.right){
stack.push([node.right,remain-node.val]);
}
}
return result;
};
/**
* 递归解法
*/
var hasPathSum = function(root, sum) {
return trans(root,0,sum);
};
var trans = function(node, total, sum){
if(!node){
return false;
}
if(node.left===null&&node.right===null){
return total + node.val === sum;
}
return trans(node.left, total+node.val, sum) || trans(node.right, total+node.val, sum);
}
旋转数组(LeetCode 189)
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
思路:
[1,2,3,4,5,6,7]
[7,6,5,4,3,2,1] 反转数组
[5,6,7|1,2,3,4] 从第k个位置两边分别反转
/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function(nums, k) {
let len = nums.length;
let forward = k % len;
reverse(nums,0,len-1);
reverse(nums,0,forward-1);
reverse(nums,forward,len-1);
};
var reverse = function(nums,start,end){
while(start<end){
let temp = nums[start];
nums[start]=nums[end];
nums[end] = temp;
start++;
end--;
}
}