100. 相同的树 (简单)
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
因为遍历的函数有返回值,所以递归左右子树时,要用变量去接住。
!(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. 二叉树的锯齿形层序遍历 (中等)
给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
通过变量规定加入到列表的方向,实际只是对层次遍历的结果进修修改。对于对层次遍历练练手:
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 (中等)
给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
又是对层次遍历的结果进修修改,只改一行 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 ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
完全二叉树比普通二叉树特殊,但又没有满二叉树那么特殊,计算它的节点总数,可以说是普通二叉树和完全二叉树的结合版
文章直接上答案了,它不用考虑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
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
最近公共祖先(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 // 好比在一边找到目标节点,拿着目标节点要向上通报
};
124. 二叉树中的最大路径和 (困难)
路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 root ,返回其 最大路径和 。
启发我的是:一个节点有三个方向,因为路径,我们只能三选二。
观察当 b 作为根节点root ,不考虑它的父亲,实际我们递归时也无法得到。所以就只能考虑 d - b - e 的总和。对于b肯定舍弃小于0的子树。当b作为根节点结束时,他要向上层汇报,如果他是负数,也要如实汇报,至于他的父亲会自己判断(针对所有节点都是负值)。这时,面临三选二情况,对于b就是二选一。
let maxsum = null
function maxGain(root) {
if(root == null) return 0
let leftsum = Math.max(maxGain(root.left), 0)
let rightsum = Math.max(maxGain(root.right), 0)
let cursum = leftsum + rightsum + root.val
if(cursum > maxsum) maxsum = cursum
let construction = root.val + (leftsum > rightsum ? leftsum : rightsum)
return construction
}
var maxPathSum = function(root) {
maxsum = Number.MIN_SAFE_INTEGER
maxGain(root)
return maxsum
};
515. 在每个树行中找最大值 (中等)
给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。
层次遍历
var largestValues = function(root) {
if(root==null) return []
let deque = [root], ans = []
while(deque.length) {
let len = deque.length, tmp = Number.MIN_SAFE_INTEGER;
for (let i=1; i<=len; i++){
let node = deque.shift()
if(node.val > tmp) tmp = node.val
node.left && deque.push(node.left)
node.right && deque.push(node.right)
}
ans.push(tmp)
}
return ans;
};
965. 单值二叉树 (简单)
如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。
只有给定的树是单值二叉树时,才返回 true;否则返回 false。
需要全局变量提取结束遍历
var isUnivalTree = function(root) {
if (root == null) return true
let tar = root.val, conf = true
function traverse(root) {
if(root==null) return
if(root.val!=tar) conf = false
if(conf){
traverse(root.left)
traverse(root.right)
}
}
traverse(root)
return conf
};