1. 程式人生 > 其它 >劍指offer-樹(JavaScript)

劍指offer-樹(JavaScript)

7. 重建二叉樹

題目描述

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。

例如,給出

前序遍歷 preorder = [3,9,20,15,7]
中序遍歷 inorder = [9,3,15,20,7]

返回如下的二叉樹:

    3
   / \
  9  20
    /  \
   15   7

程式碼

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {number[]} preorder
 * @param {number[]} inorder
 * @return {TreeNode}
 */
var buildTree = function(preorder, inorder) {
    if(preorder.length==0 || inorder.length==0) return null;
    var root=preorder[0];
    var index = inorder.indexOf(root);
    var left = inorder.slice(0, index);
    var right = inorder.slice(index+1);
    var node = new TreeNode(root);
    node.left = buildTree(preorder.slice(1,index+1), left);
    node.right = buildTree(preorder.slice(index+1), right);
    return node;
};

8. 二叉樹的下一個節點

題目描述

給定一個二叉樹其中的一個結點,請找出中序遍歷順序的下一個結點並且返回。注意,樹中的結點不僅包含左右子結點,同時包含指向父結點的next指標。下圖為一棵有9個節點的二叉樹。樹中從父節點指向子節點的指標用實線表示,從子節點指向父節點的用虛線表示。

例如

輸入:{8,6,10,5,7,9,11},8
返回:9
解析:這個組裝傳入的子樹根節點,其實就是整顆樹,中序遍歷{5,6,7,8,9,10,11},根節點8的下一個節點就是9,應該返回{9,10,11},後臺只打印子樹的下一個節點,所以只會列印9,如下圖,其實都有指向左右孩子的指標,還有指向父節點的指標,下圖沒有畫出來

程式碼

/*function TreeLinkNode(x){
    this.val = x;
    this.left = null;
    this.right = null;
    this.next = null;
}*/

function GetNext(pNode) {
  // write code here
  if (pNode === null) return null; //空結點
  var p = null;
  if (pNode.right) {
    //有右子樹,則下一個結點在右子樹最左邊的結點
    p = pNode.right;
    while (p.left !== null) {
      p = p.left;
    }
    return p;
  } else {
    //沒有右子樹
    p = pNode.next;
    if (p && p.right === pNode) {
      while (p.next && p.next.right === p) {
        p = p.next;
      }
      p = p.next;
    }
    return p;
  }
  return null;
}

26. 樹的子結構

題目描述

輸入兩棵二叉樹A和B,判斷B是不是A的子結構。(約定空樹不是任意一個樹的子結構)
B是A的子結構, 即 A中有出現和B相同的結構和節點值。

例如:
給定的樹 A:

  3
  / \
 4  5
 / \
1  2

給定的樹 B:

 4
 /
1

返回 true,因為 B 與 A 的一個子樹擁有相同的結構和節點值。

示例 1:

輸入:A = [1,2,3], B = [3,1]
輸出:false

示例 2:

輸入:A = [3,4,5,1,2], B = [4,1]
輸出:true

程式碼

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} A
 * @param {TreeNode} B
 * @return {boolean}
 */
var isSubStructure = function(A, B) {
    if(!A || !B) return false; 
    return isSame(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
};
var isSame = function(A, B){
    if(!B) return true;
    if(!A) return false;
    if(A.val != B.val) return false;
    return isSame(A.left, B.left) && isSame(A.right, B.right);
}

27.二叉樹的映象

題目描述

請完成一個函式,輸入一個二叉樹,該函式輸出它的映象。

例如輸入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9

映象輸出:

	 4
   /   \
  7     2
 / \   / \
9   6 3   1

示例 1:

輸入:root = [4,2,7,1,3,6,9]
輸出:[4,7,2,9,6,3,1]

程式碼

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {TreeNode}
 */
var mirrorTree = function(root) {
    if(!root) return root;
    [root.left, root.right] = [root.right, root.left];
    mirrorTree(root.left);
    mirrorTree(root.right);
    return root
};

28.對稱的二叉樹

題目描述

請實現一個函式,用來判斷一棵二叉樹是不是對稱的。如果一棵二叉樹和它的映象一樣,那麼它是對稱的。

例如,二叉樹 [1,2,2,3,4,4,3] 是對稱的。

    1
   / \
  2   2
 / \ / \
3  4 4  3

但是[1,2,2,null,3,null,3] 則不是映象對稱的:

    1
   / \
  2   2
   \   \
   3    3

示例 1:

輸入:root = [1,2,2,3,4,4,3]
輸出:true

示例 2:

輸入:root = [1,2,2,null,3,null,3]
輸出:false

程式碼

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isSymmetric = function(root) {
    if(!root) return true;
    return isSame(root.left, root.right)
};
var isSame = function(A, B){
    if(!A && !B) return true;
    if(!A) return false;
    if(!B) return false;
    if(A.val != B.val) return false;
    return isSame(A.left, B.right) && isSame(A.right, B.left); 
}

32-I.從上到下列印二叉樹

從上到下打印出二叉樹的每個節點,同一層的節點按照從左到右的順序列印。

例如:

給定二叉樹: [3,9,20,null,null,15,7],

   3
  / \
  9  20
    /  \
   15   7

返回:

[3,9,20,15,7]

程式碼

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var levelOrder = function(root) {
    if(!root) return [];
    let nodes = [];
    nodes.push(root);
    let res = [];
    while(nodes.length > 0){
        node = nodes.shift();
        res.push(node.val);
        node.left && nodes.push(node.left);
        node.right && nodes.push(node.right);
    }
    return res;
};

32-II.從上到下列印二叉樹II

題目描述

從上到下按層列印二叉樹,同一層的節點按從左到右的順序列印,每一層列印到一行。

例如:
給定二叉樹: [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其層次遍歷結果:

[
  [3],
  [9,20],
  [15,7]
]

程式碼

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
    if(!root) return []
    let nodes = [] // 存放當前節點
    let layer = 0 // 表示當前層數
    let res = []
    nodes.push(root)
    while(nodes.length){
        res[layer] = []
        let num = nodes.length
        while(num--){
            let node = nodes.shift()
            res[layer].push(node.val)
            node.left && nodes.push(node.left)
            node.right && nodes.push(node.right)
        }
        layer++
    }
    return res
};

54. 二叉搜尋樹的第k大節點

題目描述

給定一棵二叉搜尋樹,請找出其中第k大的節點。

示例 1:

輸入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
輸出: 4

示例 2:

輸入: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
輸出: 4

程式碼

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} k
 * @return {number}
 */
var kthLargest = function(root, k) {
    let res
    let num = 0
    const dfs = function(root){
        if(root === null){
            return 
        }
        dfs(root.right)
        num++
        if(num === k){
            res = root.val
        }
        dfs(root.left)
    }
    dfs(root)
    return res
};

55-I. 二叉樹的深度

題目描述

輸入一棵二叉樹的根節點,求該樹的深度。從根節點到葉節點依次經過的節點(含根、葉節點)形成樹的一條路徑,最長路徑的長度為樹的深度。

例如:

給定二叉樹 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

程式碼

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxDepth = function(root) {
    if(root === null) return 0
    return Math.max(maxDepth(root.left), maxDepth(root.right))+1
};

55-II. 平衡二叉樹

題目描述

輸入一棵二叉樹的根節點,判斷該樹是不是平衡二叉樹。如果某二叉樹中任意節點的左右子樹的深度相差不超過1,那麼它就是一棵平衡二叉樹。

示例 1:

給定二叉樹 [3,9,20,null,null,15,7]

  3
 / \		
 9  20
/  \
15   7

返回 true 。

程式碼

function IsBalanced_Solution(pRoot) {
  return depth(pRoot) !== -1;
}

// 用遞迴來判斷root是不是平衡二叉樹,如果不是則返回最大的深度,如果不是則返回-1
function depth(root) {
  if (root === null) return 0;
  var left = depth(root.left);
  if (left === -1) return -1;
  var right = depth(root.right);
  if (right === -1) return -1;
  if (Math.abs(left - right) > 1) {
    return -1;
  } else {
    return 1 + Math.max(left, right);
  }
}

68-I. 二叉搜尋樹的最近公共祖先

題目描述

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

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

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

示例 :

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

程式碼

/**
 * 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) {
    while(root){
        if(root.val<p.val && root.val<q.val){
            root = root.right
        } else if(root.val>p.val && root.val>q.val) {
            root = root.left
        } else {
            break
        }
    }
    return root
};

68-II. 二叉樹的最近公共祖先

題目描述

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

示例 1:

輸出: 3
解釋: 節點 5 和節點 1 的最近公共祖先是節點 3。```

示例 2:

輸出: 5
解釋: 節點 5 和節點 4 的最近公共祖先是節點 5。因為根據定義最近公共祖先節點可以為節點本身。```

程式碼

/**
 * 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) {
    if (!root || root === p || root === q) return root;
    const left = lowestCommonAncestor(root.left, p, q);
    const right = lowestCommonAncestor(root.right, p, q);
    // 左子樹找不到,返回右子樹
    if (!left) return right;
    // 右子樹找不到,返回左子樹
    if (!right) return left;
    // 左右子樹都找到了,那麼root就是要找的
    return root;
};