遍歷樹算法2 - Solve tree problems recursively

首先定義一棵樹node

var root = {
   val: 1,
   left:{
     val: 2,
     left: {
        val: 3,
        left: {
            val: 5
        }
     },
     right: {
        val: 4,
        right: {
            val: 6
        }
     }
   },
   right:{
       val: 7,
       left: {
           val: 8
       },
       right:{
           val: 9,
           right: {
               val: 10,
               left: {
                  val: 11,
                  right: {
                     val: 12
                  }
               }
           }    
       }
   } 
};

Max Depth of Binary Tree 計算二叉樹最大深度

The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 最大深度是指從根節點到最遠的葉節點通過的節點個數。

思路

節點若是爲空, 則 return 0.
節點若是有左節點或者右節點, 則 return depth + 1.
換算成公式則爲:
fn(n) = 0, if null;
fn(n) = 1 + max(f(n.left), f(n.right))函數

clipboard.png

以這課樹爲例,
nodeA的深度 = 1 + max(nodeB的深度, nodeC的深度)
nodeB沒有子節點,因此nodeB的深度爲1.
nodeC有子節點 [D, E], 因此nodeC的深度爲2.
因此 nodeA的最大深度 = 1 + max(1, 2) = 2.this

代碼

var maxDepth= function(root) {
  if(root == null) return 0;
  return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
};

console.warn(maxDepth(root));  // 6

Min Depth of Binary Tree 計算二叉樹最小深度

The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. 最小深度是指從根節點到最近的葉節點通過的節點個數。

思路

節點若是爲空, 則 return 0.
節點若是有左節點或者右節點, 則 return depth + 1.
換算成公式則爲:
fn(n) = 0, if null;
fn(n) = 1 + min(f(n.left), f(n.right))spa

clipboard.png

以這課樹爲例,
nodeA的深度 = 1 + min(nodeB的深度, nodeC的深度)
nodeB沒有子節點,因此nodeB的深度爲1.
nodeC有子節點 [D, E], 因此nodeC的深度爲2.
因此 nodeA的最小深度 = 1 + min(1, 2) = 2.rest

代碼

var minDepth= function(root) {
  if(root == null) return 0;
  return 1 + Math.min(minDepth(root.left), minDepth(root.right));
};

console.warn(minDepth(root));  // 3

Path Sum of Binary Tree 計算二叉樹路徑之和

Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. 斷定一個從根節點到葉子節點的路徑之和是否和給定的數值相等。

思路

進行DFS深度優先遍歷,依次將 (sum - root.val) 傳遞給遞歸函數的sum值。
若是root不存在,直接return false.
若是root不存在left和right節點, 說明是葉子節點,若sum值等於val, 則return true.
最後再對左右節點進行持續的遍歷。code

代碼

var hasPathSum = function(root, sum) {
  if (!root) return false;
  if (!root.left && !root.right && root.val === sum) return true;
  return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
};

console.warn(hasPathSum(root, 11));  // true
console.warn(hasPathSum(root, 13));  // true
console.warn(hasPathSum(root, 16));  // true
console.warn(hasPathSum(root, 45));  // true
console.warn(hasPathSum(root, 50));  // true

Symmetric Binary Tree 判斷二叉樹是否對稱

this binary tree [1,2,2,3,4,4,3] is symmetric. 這棵樹[1,2,2,3,4,4,3]是對稱的。
But the following [1,2,2,null,3,null,3] is not. 這棵樹[1,2,2,null,3,null,3]不是對稱的。

思路

若是根節點不存在,則直接return true.
若是node節點不存在左右子樹, 則return true.
若是node節點存在左子樹,或者右子樹, 則return false.
若是node節點存在左右子樹,可是節點的值不相等, 則return false.
接下來比較左子樹的左節點和右子樹的右節點, 左子樹的右節點和右子樹的左節點, 都相同時return true.blog

代碼

var isSymmetric = function(root) {
    if(!root) return true;
    
    function compareNodes(left, right) {
        if (!left && !right) return true;
        if (!left || !right) return false;
        if (left.val !== right.val) return false;
        
        return (compareNodes(left.left, right.right) && compareNodes(left.right, right.left));
    }
    return compareNodes(root.left, root.right);
};

isSymmetric(root);   // false

var root2 = {
   val: 1,
   left:{
     val: 2,
     left: {
        val: 3,
        left: {
            val: 5
        }
     },
     right: {
        val: 4,
        right: {
            val: 6
        }
     }
   },
   right:{
       val: 2,
       right: {
        val: 3,
        right: {
            val: 5
        }
     },
     left: {
        val: 4,
        left: {
            val: 6
        }
     }
   } 
};
isSymmetric(root2);  // true

二叉樹反轉

其實就是二叉樹的左右節點互換,深度遍歷。遞歸

function reverseLeftRightNodes(node) {
        if(node === null || node === undefined) return;
        
        let temp = node.left;
        node.left = node.right;
        node.right = temp;
        
        reverseLeftRightNodes(node.left);
        reverseLeftRightNodes(node.right);
        return node;
    }
相關文章
相關標籤/搜索