当前位置: 首页 > 知识库问答 >
问题:

在二叉树中打印具有给定和的所有路径的算法

金阳华
2023-03-14

以下是一个采访问题。

您将获得一个二叉树(不一定是BST),其中每个节点都包含一个值。设计一个算法来打印所有总计为该值的路径。注意,它可以是树中的任何路径-它不必从根开始。

虽然我能够找到树中从根开始的所有路径都有给定的总和,但对于不是从根开始的路径,我无法这样做。

共有3个答案

东门晨
2023-03-14

基于上面Christian的回答:

public void printSums(Node n, int sum, int currentSum, String buffer) {
     if (n == null) {
         return;
     }
     int newSum = currentSum + n.val;
     String newBuffer = buffer + " " + n.val;
     if (newSum == sum) {
         System.out.println(newBuffer);
     }
     printSums(n.left, sum, newSum, newBuffer);
     printSums(n.right, sum, newSum, newBuffer);
     printSums(n.left, sum, 0, "");
     printSums(n.right, sum, 0, "");
} 

printSums(root, targetSum, 0, "");
费辰阳
2023-03-14

这里有一个O(n numResults)答案(基本上与@某人的答案相同,但所有问题都已解决):

  1. 对二叉树进行前序、按序或后序遍历。
  2. 在进行遍历时,维护从根节点到当前节点上方节点的节点值的累积和。让我们将此值称为累积量SumBeforeNode
  3. 当您在遍历中访问一个节点时,将其添加到key的哈希表中(该key的值将是节点列表)。
  4. 计算umulativeSumBeforeNode和目标总和之间的差异。在哈希表中查找此差异。
  5. 如果哈希表查找成功,它应该生成一个节点列表。这些节点中的每一个都代表解决方案的开始节点。当前节点代表每个相应开始节点的结束节点。将每个[开始节点,结束节点]组合添加到您的答案列表中。如果哈希表查找失败,则什么都不做。
  6. 在遍历中访问完一个节点后,从哈希表中存储在keyumulativeSumBeforeNode的列表中删除该节点。

代码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class BinaryTreePathsWithSum {
    public static void main(String[] args) {
        BinaryTreeNode a = new BinaryTreeNode(5);
        BinaryTreeNode b = new BinaryTreeNode(16);
        BinaryTreeNode c = new BinaryTreeNode(16);
        BinaryTreeNode d = new BinaryTreeNode(4);
        BinaryTreeNode e = new BinaryTreeNode(19);
        BinaryTreeNode f = new BinaryTreeNode(2);
        BinaryTreeNode g = new BinaryTreeNode(15);
        BinaryTreeNode h = new BinaryTreeNode(91);
        BinaryTreeNode i = new BinaryTreeNode(8);

        BinaryTreeNode root = a;
        a.left = b;
        a.right = c;
        b.right = e;
        c.right = d;
        e.left = f;
        f.left = g;
        f.right = h;
        h.right = i;

        /*
                5
              /   \
            16     16
              \     \
              19     4
              /
             2
            / \
           15  91
                \
                 8
        */

        List<BinaryTreePath> pathsWithSum = getBinaryTreePathsWithSum(root, 112); // 19 => 2 => 91

        System.out.println(Arrays.toString(pathsWithSum.toArray()));
    }

    public static List<BinaryTreePath> getBinaryTreePathsWithSum(BinaryTreeNode root, int sum) {
        if (root == null) {
            throw new IllegalArgumentException("Must pass non-null binary tree!");
        }

        List<BinaryTreePath> paths = new ArrayList<BinaryTreePath>();
        Map<Integer, List<BinaryTreeNode>> cumulativeSumMap = new HashMap<Integer, List<BinaryTreeNode>>();

        populateBinaryTreePathsWithSum(root, 0, cumulativeSumMap, sum, paths);

        return paths;
    }

    private static void populateBinaryTreePathsWithSum(BinaryTreeNode node, int cumulativeSumBeforeNode, Map<Integer, List<BinaryTreeNode>> cumulativeSumMap, int targetSum, List<BinaryTreePath> paths) {
        if (node == null) {
            return;
        }

        addToMap(cumulativeSumMap, cumulativeSumBeforeNode, node);

        int cumulativeSumIncludingNode = cumulativeSumBeforeNode + node.value;
        int sumToFind = cumulativeSumIncludingNode - targetSum;

        if (cumulativeSumMap.containsKey(sumToFind)) {
            List<BinaryTreeNode> candidatePathStartNodes = cumulativeSumMap.get(sumToFind);

            for (BinaryTreeNode pathStartNode : candidatePathStartNodes) {
                paths.add(new BinaryTreePath(pathStartNode, node));
            }
        }

        populateBinaryTreePathsWithSum(node.left, cumulativeSumIncludingNode, cumulativeSumMap, targetSum, paths);
        populateBinaryTreePathsWithSum(node.right, cumulativeSumIncludingNode, cumulativeSumMap, targetSum, paths);

        removeFromMap(cumulativeSumMap, cumulativeSumBeforeNode);
    }

    private static void addToMap(Map<Integer, List<BinaryTreeNode>> cumulativeSumMap, int cumulativeSumBeforeNode, BinaryTreeNode node) {
        if (cumulativeSumMap.containsKey(cumulativeSumBeforeNode)) {
            List<BinaryTreeNode> nodes = cumulativeSumMap.get(cumulativeSumBeforeNode);
            nodes.add(node);
        } else {
            List<BinaryTreeNode> nodes = new ArrayList<BinaryTreeNode>();
            nodes.add(node);
            cumulativeSumMap.put(cumulativeSumBeforeNode, nodes);
        }
    }

    private static void removeFromMap(Map<Integer, List<BinaryTreeNode>> cumulativeSumMap, int cumulativeSumBeforeNode) {
        List<BinaryTreeNode> nodes = cumulativeSumMap.get(cumulativeSumBeforeNode);
        nodes.remove(nodes.size() - 1);
    }

    private static class BinaryTreeNode {
        public int value;
        public BinaryTreeNode left;
        public BinaryTreeNode right;

        public BinaryTreeNode(int value) {
            this.value = value;
        }

        public String toString() {
            return this.value + "";
        }

        public int hashCode() {
            return Integer.valueOf(this.value).hashCode();
        }

        public boolean equals(Object other) {
            return this == other;
        }
    }

    private static class BinaryTreePath {
        public BinaryTreeNode start;
        public BinaryTreeNode end;

        public BinaryTreePath(BinaryTreeNode start, BinaryTreeNode end) {
            this.start = start;
            this.end = end;
        }

        public String toString() {
            return this.start + " to " + this.end;
        }
    }
}

凤自珍
2023-03-14

这是一棵树,不是一个图。所以,你可以这样做:

伪代码:

global ResultList

function ProcessNode(CurrentNode, CurrentSum)
    CurrentSum+=CurrentNode->Value
    if (CurrentSum==SumYouAreLookingFor) AddNodeTo ResultList
    for all Children of CurrentNode
          ProcessNode(Child,CurrentSum)

好的,这给了你从根开始的路径。然而,你可以做一个小小的改变:

    for all Children of CurrentNode
          ProcessNode(Child,CurrentSum)
          ProcessNode(Child,0)

你可能需要考虑一下(我正忙于其他事情),但这应该基本上运行植根于树中每个节点的相同算法

编辑:这实际上只给出了“结束节点”。但是,由于这是一棵树,您可以从这些结束节点开始,然后往后走,直到获得所需的总和。

编辑2:当然,如果所有值都为正,那么如果当前总和为,则可以中止下降

 类似资料:
  • 我试图打印二叉树的所有路径(根到叶的路径),但没有效果。 我的策略是使用递归,基本情况是树为None或树节点为leaf return,否则,遍历树的左侧和右侧。 但我找不到同时保留左右树的方法。

  • 问题内容: 我试图使用Java在二叉树中打印所有根到叶的路径。 在主要方法中: 但是它给出了错误的输出。 给定的树: 预期产量: [5,1,3] [5、8、6] [5、8、9] 但是输出产生了: [5,1,3] [5、1、3、8、6] [5、1、3、8、6、9] 可以找出一个… 问题答案: 用以下方法调用递归方法: 传递时会发生什么(而不是在所有方法调用中使用单个对象,这意味着,当您返回原始调用者

  • 本文向大家介绍Java实现打印二叉树所有路径的方法,包括了Java实现打印二叉树所有路径的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Java实现打印二叉树所有路径的方法。分享给大家供大家参考,具体如下: 问题: 给一个二叉树,把所有的路径都打印出来。 比如,对于下面这个二叉树,它所有的路径为: 8 -> 3 -> 1 8 -> 2 -> 6 -> 4 8 -> 3 -> 6 ->

  • 试图计算二叉树中从根到叶的路径和。似乎不起作用,doesIt的值变为true,但由于它是递归的,所以当堆栈弹出时,它会切换回false。我不知道怎么修。如何更改代码,使doesIt的值更改为true后,它会一直向上传播? 考虑树:[5,4,8,11, null, null, null,7,2]无序 5有两个孩子4和8,4有一个孩子11,8没有孩子 hasPathSum(根,22)

  • 给定一棵二叉树,问题是找到所有根到叶的路径。我们通过以列表的形式传递路径,并在到达叶子时将其添加到结果中来了解算法。 我的问题是存储所有路径需要多少空间。我的直觉是,每条路径将消耗树高度(O(h))的内存顺序,如果我们的完整二叉树中有2*n-1个节点,那么每个节点对应于一条路径,因此假设树高度平衡,空间复杂度将为O(n*log(n))。我的分析正确吗?

  • 我试图找到从根到叶的最小路径和,还需要计算最小路径。如果解决方案在左子树中,我的解决方案有效,但是如果结果在右子树中,根节点在结果路径中添加了两次,是否有人可以查看我的解决方案并帮助我修复此错误,如果有,还可以建议更好的运行时解决方案 我正在使用回溯访问所有节点,我认为我的解决方案的时间复杂度将是O(N)(因为所有节点都应该被访问,如果我错了,请纠正我)