簡體   English   中英

給定一棵二叉樹和一個和,找到所有從根到葉的路徑,其中每個路徑的和等於給定的和

[英]Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum

為什么最后要使用“ path.remove(path.size()-1)”?

該代碼用於查找總和等於給定總和的所有根到葉路徑。

public List<List<Integer>> pathSum(TreeNode root, int sum) {
    List<List<Integer>> res = new ArrayList<List<Integer>>();
    ArrayList<Integer> path = new ArrayList<Integer>();
    pathSumRe(root, sum, res, path);
    return res;
}
public void pathSumRe(TreeNode root, int sum, List<List<Integer>> res,
        ArrayList<Integer> path) {

    if (root == null)
        return;

    path.add(root.val);

    if (root.left == null && root.right == null && root.val == sum) {

        ArrayList<Integer> tmp = new ArrayList<Integer>(path);
        res.add(tmp);
    }

    pathSumRe(root.left, sum - root.val, res, path);
    pathSumRe(root.right, sum - root.val, res, path);
    path.remove(path.size() - 1);
}

刪除“ path.remove(path.size()-1);” 從代碼中將給出以下輸出。

輸入:[0,1,1],1

輸出:[[0,1],[0,1,1]] ==>這是錯誤的輸出

預期輸出:[[0,1],[0,1]]

path.remove(path.size() - 1)正在從path列表中刪除最后一個添加的節點,因為您將所有遞歸迭代使用相同的列表,並使用path.add(root.val);添加當前節點path.add(root.val); 在每個方法執行中。


在不重新使用相同列表(並為每次執行創建一個新列表)的情況下,以下內容是等效的:

public void pathSumRe(TreeNode root, int sum, List<List<Integer>> res,
        ArrayList<Integer> path) {
    if (root == null) {
        return;
    }
    path.add(root.val);
    if (root.left == null && root.right == null && root.val == sum) {
        res.add(new ArrayList<Integer>(path));
    }
    pathSumRe(root.left, sum - root.val, res, new ArrayList<Integer>(path));
    pathSumRe(root.right, sum - root.val, res, new ArrayList<Integer>(path));
}

這比較容易理解,但是會創建更多新的ArrayList (取決於樹結構)。 無論您進行何種編輯,兩個版本對於TreeNode都可以正常運行,如下所示:

class TreeNode {
    public final int val;
    public final TreeNode left;
    public final TreeNode right;

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

這是干凈的Java實現:

public static List<List<Integer>> rootToLeafPathsForSum(BinaryTreeNode<Integer> node, int requiredSum) {
    List <List<Integer>> paths = new ArrayList<List<Integer>>();
    doFindRootToLeafPathsForSum(node, 0, requiredSum, new ArrayList<Integer>(), paths);
    return paths;
}

private static void doFindRootToLeafPathsForSum(BinaryTreeNode<Integer> node, int sum, int requiredSum,
        List<Integer> path, List<List<Integer>> paths) {
    if(node == null) {
        return ;
    } 
    path.add(node.getData());
    sum +=node.getData();
    if (node.isLeafNode()) {
        if (sum == requiredSum) {
            paths.add(new ArrayList<Integer>(path));
        }           
    } else {
        doFindRootToLeafPathsForSum(node.getLeft(), sum,  requiredSum, path, paths);
        doFindRootToLeafPathsForSum(node.getRight(), sum, requiredSum, path, paths);

    }
    path.remove(node.getData());
}

這是測試用例

@Test
public void allRoot2LeafPathsForGivenSum() {
    BinaryTreeNode<Integer> bt = buildTree();
    List <List<Integer>> paths = BinaryTreeUtil.rootToLeafPathsForSum(bt, 14);

    assertThat(paths.size(), is(2));

    assertThat(paths.get(0).toArray(new Integer[0]), equalTo(new Integer[]{1,2,5,6}));
    assertThat(paths.get(1).toArray(new Integer[0]), equalTo(new Integer[]{1,3,7,3}));

    for (List<Integer> list : paths) {          
        for (Integer integer : list) {
            System.out.print(String.format(" %d", integer));
        }
        System.out.println();
    }
}

private BinaryTreeNode<Integer> buildTree() {
    BinaryTreeNode<Integer> n4 = new BinaryTreeNode<Integer>(4);
    BinaryTreeNode<Integer> n6 = new BinaryTreeNode<Integer>(6);
    BinaryTreeNode<Integer> n5 = new BinaryTreeNode<Integer>(5, null, n6);
    BinaryTreeNode<Integer> n2= new BinaryTreeNode<Integer>(2, n4, n5);
    BinaryTreeNode<Integer> n31 = new BinaryTreeNode<Integer>(3);
    BinaryTreeNode<Integer> n7 = new BinaryTreeNode<Integer>(7, null, n31);
    BinaryTreeNode<Integer> n3 = new BinaryTreeNode<Integer>(3, n7, null);
    BinaryTreeNode<Integer> root = new BinaryTreeNode<Integer>(1, n2, n3);

    return root;
}

您需要的是檢查到現在為止所經過的路徑的方法,如果是,則將其加和直到葉的總和,如果是,則添加該列表以得到結果,否則不需要回溯,這是本例中最重要的步驟! 我希望代碼能使它更清晰-

void util(TreeNode root, int sum, ArrayList<Integer>log, ArrayList<ArrayList<Integer>> result)
{
    if(root == null)    
        return;
    log.add(root.val);
    if(root.left == null && root.right == null && sum - root.val == 0)
        result.add(new ArrayList<Integer>(log));
    util(root.left, sum-root.val, log, result);
    util(root.right, sum-root.val, log, result);
    log.remove(log.size()-1);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM