100. 相同的树 (简单)
因为遍历的函数有返回值,所以递归左右子树时,要用变量去接住。
!(p && q) 只要有一个为null ,表达式为true
var isSameTree = function(p, q) {
if (p==null && q==null) return true
if (!(p && q) || p.val != q.val) return false
let left = isSameTree(p.left, q.left)
let right = isSameTree(p.right, q.right)
return left && right
};
代码属于先序遍历
103. 二叉树的锯齿形层序遍历 (中等)
通过变量规定加入到列表的方向,实际只是对层次遍历的结果进修修改。对于对层次遍历练练手:
var zigzagLevelOrder = function(root) {
if(root == null) return []
let deque = [root], flag = true, ans=[]
while(deque.length) {
let temp = [], len = deque.length
for (let i=1; i<=len; i++){
let root = deque.shift()
flag ? temp.push(root.val) : temp.unshift(root.val)
root.left && deque.push(root.left)
root.right && deque.push(root.right)
}
flag = !flag
ans.push(temp)
}
return ans;
};
107. 二叉树的层序遍历 II (中等)
又是对层次遍历的结果进修修改,只改一行 ans.unshift(temp)
111. 二叉树的最小深度 (简单)
该题是BFS算法,就是层次遍历,记录每一层深度,遇到叶子节点就结束。
我用递归来完成,但需要避开导致错误的情形。
当没有左孩子,递归时返回0,但实际它没有左子树。
我的逻辑是,如果没有左子树,那么他返回的深度left就不能使用。右子树也一样操作。如果是叶子节点,他没有右子树和左子树,则left和right都不能用,所以直接返回1。
var minDepth = function(root) {
if(root == null) return 0
let left = minDepth(root.left)
let right = minDepth(root.right)
let min = null
if(root.left) min = left
if(root.right) {
min = right
if(root.left && left<right) min = left;
}
if(min==null) min = 0
return min + 1
};
但其实有简洁方式,因为left和right虽然不能用,但他们的值为0。
层次遍历解法
var minDepth = function(root) {
if(root == null) return 0
let deque = [root], depth = 1
while(deque.length){
let len = deque.length
for (let i=1; i<=len; i++){
let root = deque.shift()
if(root.left == null && root.right == null) return depth
root.left && deque.push(root.left)
root.right && deque.push(root.right)
}
depth++
}
return depth;
};
222. 完全二叉树的节点个数 (中等) fail
更高效的方法
完全二叉树比普通二叉树特殊,但又没有满二叉树那么特殊,计算它的节点总数,可以说是普通二叉树和完全二叉树的结合版
文章直接上答案了,它不用考虑root == null,因为叶子节点时,它的节点数就是math.pow(2,1)- 0 = 1
var countNodes = function(root) {
let l = r = root, hl = hr = 0;
while(l){
l=l.left;
hl++;
}
while(r){
r=r.right;
hr++;
}
if(hl==hr) return Math.pow(2, hl) - 1;
return 1 + countNodes(root.left) + countNodes(root.right);
};
后面才说明一下,这个算法的时间复杂度是 O(logN*logN):
一棵完全二叉树的两棵子树,至少有一棵是满二叉树:.
236. 二叉树的最近公共祖先 (中等)fail
最近公共祖先(Lowest Common Ancestor,简称 LCA)
这道题也在剑指 Offer 68为简单题 当时用的数组记录两条搜索路径。
遇到任何递归型的问题,无非就是灵魂三问:
1、这个函数是干嘛的?root是不固定的
2、这个函数参数中的变量是什么的是什么?
3、得到函数的递归结果,你应该干什么?
可以试着写出递归代码
var lowestCommonAncestor = function(root, p, q) {
if (root == null) return null
if (root == p || root == q) return root // q为p的子节点时,到最后就只找到p,但p就是答案
let left = lowestCommonAncestor(root.left, p, q)
let right = lowestCommonAncestor(root.right, p, q)
if(left==null && right==null) return null
if(left && right) return root
return left ? left : right // 好比在一边找到目标节点,拿着目标节点要向上通报
};