JavaScript:leetcode_236. 二叉樹的最近公共祖先(1. 層序遍歷 + 二叉樹任意遍歷方法 2. 二叉樹遍歷 + 動態規劃)

題目說明

給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。

百度百科中最近公共祖先的定義爲:“對於有根樹 T 的兩個結點 p、q,最近公共祖先表示爲一個結點 x,
滿足 x 是 p、q 的祖先且 x 的深度儘可能大(一個節點也可以是它自己的祖先)。”

例如,給定如下二叉樹:  root = [3,5,1,6,2,0,8,null,null,7,4]

在這裏插入圖片描述


示例 1:

輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
輸出: 3
解釋: 節點 5 和節點 1 的最近公共祖先是節點 3。
示例 2:

輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
輸出: 5
解釋: 節點 5 和節點 4 的最近公共祖先是節點 5。因爲根據定義最近公共祖先節點可以爲節點本身。
 

說明:

所有節點的值都是唯一的。
p、q 爲不同節點且均存在於給定的二叉樹中。

解題思路一

  1. 層序遍歷二叉樹,每遍歷到一個節點,就收集該節點在內的所有子節點
  2. 該節點子節點集合中是否同時存在p,q,如果存在,標記該節點,flag爲true代表:該節點是p,q的一個公共祖先,然後依次遍歷其左右節點子節點集合
  3. 若不存在,說明其子節點的集合肯定也不存在,就中斷遞歸,沒必要再繼續了。
  4. 最終遞歸會在左右節點都不存在的情況下終止遍歷。形成一個帶有標記的樹,每個節點上標記有flag爲true的都是p,q的公共祖先
  5. 最後再進行一次層序遍歷,收集flag爲true的節點,然後數組的末尾一位就是他們的最近公共祖先。

注意: 題目中的5,步驟也可以放在 2-3步驟中同時進行收集。
代碼實現中,我使用了unshift(),所以輸出的是第一位。

代碼實現一

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
// 注意是返回節點,不是返回節點的值!!!
var lowestCommonAncestor = function(root, p, q) {
    p = p.val;
    q = q.val;
    find(root, p, q);
    let help = [root]
    let res = [];
    while (help.length) {
        let now = help.shift();
        if(now.flag) {
            res.unshift(now);
            now.left && help.push(now.left);
            now.right && help.push(now.right);
        }
    }
    return res[0]
};

function find(root, p, q) {
    let help = [root]
    let res = [];
    while (help.length) {
        let now = help.shift();
        res.push(now.val);
        now.left && help.push(now.left);
        now.right && help.push(now.right);
    }
    if (res.indexOf(p) !== -1 && res.indexOf(q) !== -1) {
        root.flag = true;
        root.left && (find(root.left, p, q))
        root.right && (find(root.right, p, q))
    }
}

解題思路二

  1. 收集所有的節點的祖先節點,類似於動態規劃,每個節點的所有公共祖先都是父節點所有公共祖先的加上該節點本身
  2. 通過動態規劃和遞歸進行收集。
  3. 判斷該節點是否是p或者q收集到對象中。
  4. 二叉樹遍歷完成後,將收集到的p,q所有的祖先節點進行遍歷,倒序遍歷第一個相同的節點就是他們的最近公共祖先

這個方法在實際提交中,超內存了。。。但是思路應該是沒毛病的。

代碼實現一

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
// 注意是返回節點,不是返回節點的值!!!
var lowestCommonAncestor = function(root, p, q) {
    p = p.val;
    q = q.val;
    let res = {
        p: [],
        q: []
    }
    find(root, p, q, [], res);
    for (let i = res.q.length; i >= 0; i--) {
        if (res.p.indexOf(res.q[i]) !== -1) {
            return res.q[i]
        }
    }
};

function find(root, p, q, prev, res) {
    prev = [...prev, root];
    if (root.val === p) {
       res.p = [...prev]
    }
    if (root.val === q) {
       res.q = [...prev]
    }
    root.left && (find(root.left, p, q, prev, res));
    root.right && (find(root.right, p, q, prev, res));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章