1.二叉樹的最大深度
題目:
給定一個二叉樹,找出其最大深度。
二叉樹的深度爲根節點到最遠葉子節點的最長路徑上的節點數。
說明: 葉子節點是指沒有子節點的節點。
思路:要得到深度,就要遍歷樹,高度是一層一層累加的,所以採用遞歸的辦法,逐級的獲取高度,如果存在左節點或者右節點則自增1,然後計算下一個節點的深度。
var maxDepth = function(root) {
if (!root) return 0;
const a = (root, length) => {
if (!root.left && !root.right) {
return length;
} else if (!root.left) {
return a(root.right, length + 1);
} else if (!root.right) {
return a(root.left, length + 1);
} else {
return Math.max(a(root.right, length + 1), a(root.left, length + 1));
}
};
return a(root, 1);
};
問題:判斷太多,因爲已經判斷了當前節點爲null的情況,不需要再判斷left或者right是否爲null了
var maxDepth = function(root) {
if (!root) return 0;
return Math.max(maxDepth(root.right), maxDepth(root.left)) + 1;
};
迭代的思路:可以每次都把當前層的節點的子節點丟進一個數組,然後判斷這個數組的長度,如果長度大於0則說明有下一層。下一輪循環就遍歷這個數組,重複,最後沒有子節點時跳出循環
var maxDepth = function(root) {
if (!root) return 0;
var v = [root],
r = [],
res = 1;
while (v.length) {
v.forEach((i) => {
if (i.left) r.push(i.left);
if (i.right) r.push(i.right);
});
if (r.length) {
v = r;
r = [];
res++;
} else {
break;
}
}
return res;
};
2.二叉樹的層次遍歷
題目:給定一個二叉樹,返回其節點值自底向上的層次遍歷。 (即按從葉子節點所在層到根節點所在的層,逐層從左向右遍歷)
思路:和上一題的循環解法非常像,每次把結果放到最前面即可。
var levelOrderBottom = function(root) {
if (!root) return [];
var v = [root],
r = [];
while (true) {
var a = [],
t = [];
v.forEach((i) => {
t.push(i.val);
if (i.left) {
a.push(i.left);
}
if (i.right) {
a.push(i.right);
}
});
r.unshift(t);
if (a.length) {
v = a;
} else {
break;
}
}
return r;
};
3.將有序數組轉換爲二叉搜索樹
題目:
將一個按照升序排列的有序數組,轉換爲一棵高度平衡二叉搜索樹。
本題中,一個高度平衡二叉樹是指一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1。
思路:分治法,想象一下,每次取中間節點,左邊的節點組成一顆子樹,放在這個節點的左邊,右邊的節點組成一顆子樹,放在這個節點的右邊,然後左右的節點數組遞歸調用,知道長度小於2。.長度爲0時直接返回null,長度爲1時返回這個節點。最終就得到了二叉樹
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {number[]} nums
* @return {TreeNode}
*/
var sortedArrayToBST = function(nums) {
let l = nums.length;
if (!l) return null;
if (l === 1) return new TreeNode(nums[0]);
const middle = Math.floor(l / 2);
const mn = new TreeNode(nums[middle]);
mn.left = sortedArrayToBST(nums.slice(0, middle));
mn.right = sortedArrayToBST(nums.slice(middle + 1));
return mn;
};
4.平衡二叉樹
題目:
給定一個二叉樹,判斷它是否是高度平衡的二叉樹。
本題中,一棵高度平衡二叉樹定義爲:一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過1。
思路:遞歸求解,在每次執行函數時,判斷某個節點的左右兩個子樹各自是否高度平衡,然後判斷兩個子樹之間的高度是否只相差1.
const a = (v) => {
if (!v) return 0;
return Math.max(a(v.left), a(v.right)) + 1;
};
var isBalanced = function(root) {
if (!root) return true;
return (
isBalanced(root.left) &&
isBalanced(root.right) &&
Math.abs(a(root.left) - a(root.right)) < 2
);
};
5.二叉樹的最小深度
題目:
給定一個二叉樹,找出其最小深度。
最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。
說明: 葉子節點是指沒有子節點的節點。
思路:這個和之前的一個求最大深度的很像,遞歸求解即可
var minDepth = function(root) {
if(!root)return 0
if(root.left&&root.right){
return Math.min(minDepth(root.left),minDepth(root.right))+1
}else if(root.left){
return minDepth(root.left)+1
}else{
return minDepth(root.right)+1
}
};
循環解法:
var minDepth = function(root) {
if (!root) return 0;
let stack = [root];
let res = 1,
item;
while (true) {
let l = stack.length;
for (let i = 0; i < l; i++) {
item = stack.shift();
if (!item.left && !item.right) {
return res;
} else {
if (item.left) stack.push(item.left);
if (item.right) stack.push(item.right);
}
}
res++;
}
};
遞歸的優化:不需要遍歷樹的每個節點,只需要在遍歷的時候保存之前遞歸的最小結果,然後在遞歸過程中如果當前深度已經超過這個值,則直接停止這個子樹的遞歸。
var min = (node, res, currD = 0) => {
currD++;
if (currD >= res.v) {
return;
}
if (!node.left && !node.right && currD < res.v) {
res.v = currD;
}
if (node.left) min(node.left, res, currD);
if (node.right) min(node.right, res, currD);
};
var minDepth = function(root) {
if (!root) return 0;
var res = { v: Infinity };
min(root, res);
return res.v;
};