【LeetCode】每日一題129:求根到葉子節點數字之和

喜歡下雨所以愛上雷震子發表於2020-10-29

129.求根到葉子節點數字之和

給定一個二叉樹,它的每個結點都存放一個 0-9 的數字,每條從根到葉子節點的路徑都代表一個數字。
例如,從根到葉子節點路徑 1->2->3 代表數字 123。
計算從根到葉子節點生成的所有數字之和。
說明: 葉子節點是指沒有子節點的節點。

示例 1:

  • 輸入: [1,2,3]
    1
    / \
    2 3
  • 輸出: 25
  • 解釋:
    從根到葉子節點路徑 1->2 代表數字 12.
    從根到葉子節點路徑 1->3 代表數字 13.
    因此,數字總和 = 12 + 13 = 25.

示例 2:

  • 輸入: [4,9,0,5,1]
    4
    / \
    9 0
    / \
    5 1
  • 輸出: 1026
  • 解釋:
    從根到葉子節點路徑 4->9->5 代表數字 495.
    從根到葉子節點路徑 4->9->1 代表數字 491.
    從根到葉子節點路徑 4->0 代表數字 40.
    因此,數字總和 = 495 + 491 + 40 = 1026.

節點類如下:

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

思考:

題目是計算「根節點」到每個「葉子節點」對應的數字之和,必然需要遍歷二叉樹的每個「葉子節點」,首先想到「深度優先遍歷」。當然,「廣度優先遍歷」也能解決問題,稍微複雜一些。

「深度優先遍歷」:沿著一條路一直走到底,然後從這條路盡頭的節點回退到上一個節點,再從另一條路開始走到底…,不斷遞迴重複此過程。

「廣度優先遍歷」:指的是從圖的一個未遍歷的節點出發,先遍歷這個節點的相鄰節點,再依次遍歷每個相鄰節點的相鄰節點。

「葉子節點」:沒有兒子的節點。

關於兩種遍歷的詳解,可以參考此文章,講得非常好:https://developer.51cto.com/art/202004/614590.htm

方法一:深度優先遍歷

摘自官方解答:從根節點開始,遍歷每個節點,如果遇到葉子節點,則將葉子節點對應的數字加到數字之和。如果當前節點不是葉子節點,則計算其子節點對應的數字,然後對子節點遞迴遍歷。

這裡用了一個巧妙的方式:當前節點的計算值 = 父節點的計算值 × 10 + 當前節點的值
對應程式碼中 sum = sum * 10 + root.val

public int sumNumbers(TreeNode root) {
    int sum = 0;
    return sum(root, sum);
}

public int sum(TreeNode root, int sum){
    if (root == null) {
        return 0;
    }
    sum = sum * 10 + root.val;
    if (root.left == null && root.right == null) {
        return sum;
    }
    return sum(root.left, sum) + sum(root.right, sum);
}

方法二:廣度優先遍歷

同樣摘自官方解答:使用廣度優先搜尋,需要維護兩個佇列,分別儲存節點和節點對應的數字。
初始時,將根節點和根節點的值分別加入兩個佇列。每次從兩個佇列分別取出一個節點和一個數字,進行如下操作:
1.如果當前節點是葉子節點,則將該節點對應的數字加到數字之和;
2.如果當前節點不是葉子節點,則獲得當前節點的非空子節點,並根據當前節點對應的數字和子節點的值計運算元節點對應的數字,然後將子節點和子節點對應的數字分別加入兩個佇列。

public int sumNumbers2(TreeNode root) {
   if (root == null) {
        return 0;
    }

    Queue<Integer> numQueue = new LinkedList<>();
    Queue<TreeNode> nodeQueue = new LinkedList<>();
    // 初始化
    numQueue.offer(root.val);
    nodeQueue.offer(root);

    int sum = 0;
    while (!nodeQueue.isEmpty()) {
        TreeNode cur = nodeQueue.poll();
        int num = numQueue.poll();
        if (cur.left == null && cur.right == null) {
            sum += num;
        } else {
            if (cur.left != null) {
                nodeQueue.offer(cur.left);
                numQueue.offer(num * 10 + cur.left.val);
            }
            if (cur.right != null) {
                nodeQueue.offer(cur.right);
                numQueue.offer(num * 10 + cur.right.val);
            }
        }
    }
    return sum;
}

執行結果:深度優先遍歷

在這裡插入圖片描述

相關文章