二叉树专题(二),二叉树深入思考
二叉树的最近公共祖先(中等)
- 思路:递归。分两种情况——第一,p、q 分别在某节点的左右子树中;第二,p、q 中有一个自己本身就是两者的最近公共祖先,另一个在该节点的子树中。这个过程,通过递归判定 p、q 节点分别在哪两个子树上,且递归是维护的栈数据结构,由根节点开始入栈,叶子节点出栈,所以最先出栈的公共祖先就是最近的
var lowestCommonAncestor = function(root, p, q) {
let ans
let dfs = (root, p, q) => {
if (!root) return false
let lson = dfs(root.left, p, q)
let rson = dfs(root.right, p, q)
// 如果符合“两种情况”,则出结果
if ((lson && rson) || ((root.val === p.val || root.val === q.val) && (lson || rson))) {
ans = root
// 为什么这里不做返回?判断出最近公共祖先后继续往上判断出公共祖先呢?解答在代码后
}
// 在左子树、右子树、当前值等于两节点之一则都返回真
return lson || rson || root.val === p.val || root.val === q.val
}
dfs(root, p, q)
return ans
};
- 因为整个二叉树中 p、q 节点分别只有一个,且设置了 true,当最近的公共祖先找出来后,它的父节点(也是公共祖先)的另一个子节点(最近公共祖先的兄弟节点)中没有 p、q 节点,为 false,则判断条件无法达成,所以再往上的的公共祖先都不会被返回
二叉搜索树的最近公共祖先(简单)
- 思路:迭代,一次遍历。搜索树由于其本身特性,可以在寻找值得时候做一些简单的大小判断即可找到相应的位置。分三种情况讨论——第一,如果两个节点的值都比当前节点小,则意味着都在左子树,继续遍历左子树;第二,反之在右子树;第三,若非上述两种情况,则意味着两个节点分别在当前节点的左右子树上,当前节点即为最近公共祖先。所以,若为前两种情况则继续迭代,直到出现第三种情况为止
var lowestCommonAncestor = function(root, p, q) {
let res
while (true) {
// 都在左子树
if (root.val > p.val && root.val > q.val) {
root = root.left
// 都在右子树
} else if (root.val < p.val && root.val < q.val) {
root = root.right
// 在当前节点的左右子树各一个
} else {
res = root
break
}
}
return res
};
二叉树展开为链表(中等)
- 思路:递归,前序遍历+遍历赋值。首先得清除,取得的每个节点都是引用,所以直接修改取出来的节点也就是直接修改树的结构,前序遍历好理解,主要说说如何变成链表的——每个节点都按前序遍历的顺序放入了数组,然后对数组遍历,重头戏(需要仔细思考流程,试试画图):先将当前节点左子树置空,让后将右子树指向下一个元素
var flatten = function(root) {
if (!root) return []
// let list = new TreeNode(root.val)
let arr = []
let recur = (root) => {
if (!root) return
arr.push(root)
recur(root.left)
recur(root.right)
}
recur(root)
for (let i = 1; i < arr.length; i++) {
const pre = arr[i - 1]
pre.left = null
pre.right = arr[i]
}
};
BiNode(简单)
- 思路:递归。要得到从小到大排序的链表,对二叉搜索树用中序遍历即可。思路同上类似
var convertBiNode = function(root) {
if (!root) return null
let pre = null, head = null
let recur = (root) => {
if (!root) return
recur(root.left)
if (head === null) {
head = root
} else {
pre.right = root
}
pre = root
pre.left = null
recur(root.right)
}
recur(root)
return head
};
如果觉得对你有帮助的话,点个赞呗~
反正发文又不赚钱,交个朋友呗~
如需转载,请注明出处foolBirdd