【近日力扣】二叉树的最近公共祖先+ 二叉搜索树的最近公共祖先+二叉树展开为链表+BiNode

二叉树专题(二),二叉树深入思考

二叉树的最近公共祖先(中等)

  • 思路:递归。分两种情况——第一,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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值