1.二叉树的定义
力扣上的定义:
function TreeNode(val, left, right) {
this.val = (val===undefined ? 0 : val)
this.left = (left===undefined ? null : left)
this.right = (right===undefined ? null : right)
}
用类定义:
class TreeNode {
constructor(val, left, right){
this.val = (val===undefined ? 0 : val)
this.left = (left===undefined ? null : left)
this.right = (right===undefined ? null : right)
}
}
2.二叉树的递归遍历
/**
* 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 preorderTraversal = function(root) {
let array = new Array();
const preorder = function(root,array) {
if(root === null) return;
array.push(root.val);
preorder(root.left, array);
preorder(root.right, array);
}
preorder(root,array);
return array;
};
//或
var preorderTraversal = function(root) {
let array = new Array();
const preorder = function(root) {
if(root === null) return;
array.push(root.val);
preorder(root.left);
preorder(root.right);
}
preorder(root);
return array;
};
/**
* 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) {
let array = new Array();
const postorder = function(root, array) {
if(root === null) return;
postorder(root.left, array);
postorder(root.right, array);
array.push(root.val);
}
postorder(root, array);
return array;
};
/**
* 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 inorderTraversal = function(root) {
let array = new Array();
const inorder = function(root, array) {
if(root === null) return;
inorder(root.left, array);
array.push(root.val);
inorder(root.right, array);
}
inorder(root, array);
return array;
};
3.二叉树的非递归遍历
144. 二叉树的前序遍历
前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。
为什么要先加入 右孩子,再加入左孩子呢? 因为这样出栈的时候才是中左右的顺序。
动画如下:
/**
* 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 preorderTraversal = function(root) {
let stack = [];
let result = [];
let p=root;
if(p!==null) stack.push(p);
while(stack.length!==0) {
p=stack.pop();
result.push(p.val);
if(p.right!==null) stack.push(p.right);
if(p.left!==null) stack.push(p.left);
}
return result;
};
分析一下为什么刚刚写的前序遍历的代码,不能和中序遍历通用呢,因为前序遍历的顺序是中左右,先访问的元素是中间节点,要处理的元素也是中间节点,所以刚刚才能写出相对简洁的代码,因为要访问的元素和要处理的元素顺序是一致的,都是中间节点。
那么再看看中序遍历,中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中),这就造成了处理顺序和访问顺序是不一致的。
那么在使用迭代法写中序遍历,就需要借用指针的遍历来帮助访问节点,栈则用来处理节点上的元素。
/**
* 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 inorderTraversal = function(root) {
let stack = [];
let result = [];
let p=root;
while(stack.length!==0 || p) {
if(p) {
stack.push(p);
p=p.left;
}
else {
p=stack.pop();
result.push(p.val);
p=p.right;
}
}
return result;
};
再来看后序遍历,先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了,如下图:
/**
* 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) {
let stack = [];
let result = [];
let p = root;
if(p) stack.push(p);
while(stack.length!==0) {
p=stack.pop();
result.push(p.val);
if(p.left) stack.push(p.left);
if(p.right) stack.push(p.right);
}
return result.reverse();
};
/**
* 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 levelOrder = function(root) {
let queue = [];
let result = new Array();
let queuesize=0;
if(root) {
queue.push(root);
queuesize=1;
}
let p;
while(queue.length!==0){
let k=new Array();
while(queuesize--) {
p=queue.shift();
k.push(p.val);
if(p.left) {
queue.push(p.left);
}
if(p.right) {
queue.push(p.right);
}
}
result.push(k);
queuesize=queue.length;
}
return result;
};
226. 翻转二叉树
方法一:
/**
* 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 {TreeNode}
*/
var invertTree = function(root) {
let array=[];
if(root===null) return root;
let p;
array.push(root);
while(array.length!==0) {
p=array.pop();
let q=p.left;
p.left=p.right;
p.right=q;
if(p.left) {
array.push(p.left);
}
if(p.right) {
array.push(p.right);
}
}
return root;
};
方法二:
/**
* 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 {TreeNode}
*/
var invertTree = function(root) {
if(root===null) return root;
const bianli = function(root) {
let p=root.left;
root.left=root.right;
root.right=p;
if(root.left) bianli(root.left);
if(root.right) bianli(root.right);
}
bianli(root);
return root;
};
/**
* 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 {boolean}
*/
var isSymmetric = function(root) {
let p;
let arr = [];
if(root===null) return true;
arr.push(root);
let arrcount=1;
while(arr.length!==0) {
for(let i=0;i<arrcount;i++) {
p=arr.shift();
if(p) {
arr.push(p.left);
arr.push(p.right);
}
}
arrcount=arr.length;
// console.log(arr);
for(let k=0;k<(arrcount>>1);k++) {
if(arr[k]===null ||arr[arrcount-1-k]===null) {
if((arr[k]===null &&arr[arrcount-1-k]!==null)||(arr[arrcount-1-k]===null && arr[k]!==null))
return false;
}
else if(arr[k].val!==arr[arrcount-1-k].val) {
return false;
}
}
}
return true;
};
照上一道改的。
/**
* 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} p
* @param {TreeNode} q
* @return {boolean}
*/
var isSameTree = function(p, q) {
let arr = [];
arr.push(p);
arr.push(q);
let k;
let arrcount=2;
while(arr.length!==0) {
for(let k=0;k<(arrcount>>1);k++) {
if(arr[k]===null ||arr[(arrcount>>1)+k]===null) {
if((arr[k]===null &&arr[(arrcount>>1)+k]!==null)||(arr[(arrcount>>1)+k]===null && arr[k]!==null))
return false;
}
else if(arr[k].val!==arr[(arrcount>>1)+k].val) {
return false;
}
}
for(let i=0;i<arrcount;i++) {
k=arr.shift();
if(k) {
arr.push(k.left);
arr.push(k.right);
}
}
arrcount=arr.length;
}
return true;
};
572. 另一棵树的子树
也是照上一道改的。
/**
* 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
* @param {TreeNode} subRoot
* @return {boolean}
*/
var isSubtree = function(root, subRoot) {
let a = [];
const bianli = function(p) {
if(p.val===subRoot.val&&p!==null&&subRoot!==null) {
a.push(p);
}
if(p.left) bianli(p.left);
if(p.right) bianli(p.right);
}
const isSameTree = function(p, q) {
let arr = [];
arr.push(p);
arr.push(q);
let k;
let arrcount=2;
while(arr.length!==0) {
for(let k=0;k<(arrcount>>1);k++) {
if(arr[k]===null ||arr[(arrcount>>1)+k]===null) {
if((arr[k]===null &&arr[(arrcount>>1)+k]!==null)||(arr[(arrcount>>1)+k]===null && arr[k]!==null)){
return false;
}
}
else if(arr[k].val!==arr[(arrcount>>1)+k].val) {
return false;
}
}
for(let i=0;i<arrcount;i++) {
k=arr.shift();
if(k) {
arr.push(k.left);
arr.push(k.right);
}
}
arrcount=arr.length;
}
return true;
};
bianli(root);
for(let i of a) {
if(isSameTree(i,subRoot)) {
return true;
}
}
return false;
};