1. 程式人生 > 實用技巧 >java方法的呼叫

java方法的呼叫

回溯法有“通用解題法”之稱。用它可以系統地搜尋問題的所有解。

回溯法是一個既帶有系統性又帶有跳躍性的搜尋演算法。它在問題的解空間樹中,按深度優先策略,從根結點出發搜尋解空間樹。演算法搜尋至解空間樹的任一結點時,先判斷該結點是否包含問題的解。如果肯定不包含,則跳過對以該結點為根的子樹的搜尋,逐層向其祖先結點回溯;否則,進入該子樹,繼續按深度優先策略搜尋。

回溯法求問題的所有解時,要回溯到根,且根結點的所有子樹都被搜尋遍才結束。回溯法求問題的一個解時,只要搜尋到問題的一個解就可結束。

這種以深度優先方式系統搜尋問題解的演算法稱為回溯法,它適用於求解組合數較大的問題。也經常適用於求解二叉樹的相關問題,例如以下兩個二叉樹路徑總和的問題:

二叉樹是否存在某一路徑總和

示例:
給定如下二叉樹,以及目標和 sum = 22

                              5			
                             / \
                            4   8		(左)sum = sum - 5 = 17
                           /   / \
                          11  13  4		(左)sum	= sum - 4 = 13
                         /  \      \
                        7    2      1	        (左)sum = sum - 11 = 2 

返回 true, 因為存在目標和為 22 的根節點到葉子節點的路徑 5->4->11->2

使用遞迴,分別遍歷左右子樹,當左右子樹中有一個路徑滿足條件,則返回true

遞迴結束條件:root.left == null && root.right == null && sum == root.val

sum的值自頂向下 逐層遞減 sum = sum - root.val。

class Solution {
    public boolean hasPathSum(TreeNode root, int sum) {
       
        // 當前節點為空,sum 大於等於 0;例如:root = [],sum = 0、sum = 1
        if (root == null && sum >= 0) {
            return false;
        }

        // 當前節點為空,sum 小於 0;例如:root = [],sum = -1
        if (root == null && sum < 0) {
            return false;
        }

        // 當且僅當 左右孩子節點為空 且 sum = root.val 時,則找到目標
        if (root.left == null && root.right == null && sum == root.val) {
            return true;
        }

        // 遍歷目標節點的左子樹和右子樹 ,當左右子樹中有一個返回true(即找到目標) 時,則返回true;
        // sum = sum - root.val,當到達葉子節點且sum= root.val則 找到目標
        return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
    }
}

二叉樹路徑總和為某值的所有路徑

輸入一棵二叉樹和一個整數,打印出二叉樹中節點值的和為輸入整數的所有路徑。從樹的根節點開始往下一直到葉節點所經過的節點形成一條路徑。

示例:
給定如下二叉樹,以及目標和 sum = 22

              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1

返回:

[
   [5,4,11,2],
   [5,8,4,5]
]

提示:

  1. 節點總數 <= 10000

解題思路:從根節點開始遞迴遍歷,每遍歷一個節點,則把當前節點入棧。

同時判斷 sum == 當前節點.val(每遍歷一個節點時,其sum = sum - 父節點.val)。

如果到達葉子節點且sum = 當前節點.val,則說明找到了正確的路徑,就將棧內的所有元素儲存到連結串列中。

每次返回父節點前都要將棧頂的節點刪除再返回父節點。

class Solution {
    List<List<Integer>> resList = new ArrayList<>();
    LinkedList<TreeNode> stack = new LinkedList<>();

    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        if (root == null) {
            return new ArrayList<>();
        }

        findPath(root, sum);

        return resList;
    }

    public void findPath(TreeNode root, int currentSum) {

        // 將當前根節點入棧
        stack.push(root);

        // 判斷節點狀態及sum數值,找到合適的路徑就將棧內元素儲存到連結串列中
        if ((root.left == null && root.right == null) && currentSum == root.val) {

            ArrayList<Integer> list = new ArrayList<>();

            for (int i = stack.size() - 1; i >= 0; i--) {
                TreeNode node = stack.get(i);
                list.add(node.val);
            }
            resList.add(list);
        }

        // 如果不是葉子節點,則繼續遍歷其子節點
        if (root.left != null) {
            findPath(root.left, currentSum - root.val);
        }

        if (root.right != null) {
            findPath(root.right, currentSum - root.val);
        }

        // 遞迴返回其父節點前,將棧內路徑上的當前節點刪除
        stack.pop();
    }
}