【问题标题】:Algorithm to print all paths with a given sum in a binary tree在二叉树中打印具有给定总和的所有路径的算法
【发布时间】:2012-07-04 11:37:54
【问题描述】:

以下是面试题。

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

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

【问题讨论】:

  • 值有什么限制吗?是否允许它们为负数?
  • 以 root 身份重用所有其他节点的算法。
  • 尽管我在下面给出了失败的答案(如果没有用,我会删除),但我承认,除了暴力搜索之外,我认为在一般情况下我看不到面试官想要做的事情。
  • “树中的任何路径”是什么意思?它仍然必须严格向下(从根到叶),对吧?例如。 aNode -> parentOfaNode -> siblingOfaNode 不是有效路径吗?

标签: binary-tree


【解决方案1】:

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

伪代码:

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:当然,如果所有值都是正数,那么如果当前总和 >= 所需的总和,则可以中止下降

【讨论】:

  • 不错的答案@Christian,但时间复杂度是多少?我猜它是 O(n^2),因为你来自一个节点 n 访问其他节点 O(n),并且做了 n 次,因为你正在更改根,这将输出 O(n^2) .我说的有道理吗?
  • 我认为这个解决方案在尝试实施后不会起作用。
  • 如果路径从一片叶子到另一片叶子,这将无法处理这种情况。
【解决方案2】:

这是O(n + numResults) 的答案(与@Somebody 的答案基本相同,但所有问题都已解决):

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

代码:

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;
        }
    }
}

【讨论】:

  • 难道我们还需要确保找到的节点(开始和结束)在同一路径上吗?
  • @Anant:我的算法中的第 6 步确保了这一点。哈希表在任何给定时间仅包含单个根到节点路径的值。这样,我们就保证了起点和终点节点在同一条路径上。这有意义吗?
  • 有趣的算法,但是是不是有点不对劲?如果树是无序的:{19,16,5,16},root=5,root.left=16,root.right=16,target=56?我想返回的路径是 19-16-5-16。但是,根据您列出的算法,您不会得到起始节点(因为第 6 步会从地图中删除 root.left)对吗?
  • @NishantKelkar:我将“路径”解释为“严格向下(从根到叶)”,正如问题 cmets 中所假定的那样。
【解决方案3】:

根据上面克里斯蒂安的回答:

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, "");

【讨论】:

  • 错误答案!!示例测试用例 [code] 11 / \ 8 13 / \ 1 9 目标总和:18
  • 嗨@titan,我不明白 11/\8 13/\1 9 的结构应该如何。
  • 只需在 BST 中依次输入数字 11、8、13、1、9
  • 不包含从左子树节点到右子树节点的路径。说:23, 1 作为根。路径:2->1->3。对吗?
  • -1 错误。考虑一棵具有1、深度3 和sum==1 的打印路径的完全平衡树。叶节点将被打印两次。快速修复:用buffer.equals("") 的条件检查包围最后两行。
【解决方案4】:

这是一种具有nlogn 复杂性的方法。

  1. 按顺序遍历树。
  2. 同时维护所有节点以及Hashmap&lt;CumulativeSum, reference to the corresponding node&gt;中的累积和。
  3. 现在在给定节点计算从根到节点的累积总和,直到节点说这是SUM
  4. 现在在HashMap 中查找值SUM-K
  5. 如果条目存在,则在HashMap 中获取相应的节点引用。
  6. 现在我们有了从节点引用到当前节点的有效路径。

【讨论】:

  • @Somebody 这不太行。我们找到的两个节点可能不在同一路径中。我们可以通过最低共同祖先 (LCA) 查询来检查这两个节点是否属于同一路径。如果两个节点的LCA是两个节点之一,那么它们属于同一条路径。幸运的是,在 O(n) 预处理之后,可以在 O(1) 时间内回答 LCA 查询。或者,我们可以维护一个父节点到当前节点的哈希映射。然后,如果我们找到一个匹配的节点,我们可以检查它是否是当前节点的父节点。如果是,那么它们属于同一路径。
  • @Somebody 我发布了一个带有编码解决方案的答案。我的回答解决了我上面提到的问题。
  • @Somebody:比我上面描述的更简单的补救措施是在您完成访问它们时从哈希表中删除节点(在从递归返回的路上)。
【解决方案5】:

一个干净的 JAVA 解决方案。使用内部递归调用跟踪遍历的路径。

private static void pathSunInternal(TreeNode root, int sum, List<List<Integer>> result, List<Integer> path){
    if(root == null)
        return;     
    path.add(root.val);
    if(sum == root.val && root.left == null && root.right == null){
        result.add(path);
    }

    else if(sum != root.val && root.left == null && root.right == null)
        return;
    else{
        List<Integer> leftPath = new ArrayList<>(path);
        List<Integer> rightPath = new ArrayList<>(path);
        pathSunInternal(root.left, sum - root.val, result, leftPath);
        pathSunInternal(root.right, sum - root.val, result, rightPath);
    }
}

public static List<List<Integer>> pathSum(TreeNode root, int sum) {
    List<List<Integer>> result = new ArrayList<>(); 
    List<Integer> path = new ArrayList<>();
    pathSunInternal(root, sum, result, path);       
    return result;
}

【讨论】:

    【解决方案6】:

    更新:我现在看到我的回答并没有直接回答你的问题。如果它被证明有用,我会把它留在这里,但它不需要投票。如果没有用,我会删除它。我确实同意@nhahtdh,但是,当他建议“将所有其他节点作为根节点重用您的算法”时。

    一个怀疑面试官在这里钓鱼递归。不要让他失望!

    给定一个节点,您的例程应该调用自己针对其每个子节点(如果有),然后将节点自己的数据添加到返回值,然后返回总和。 p>

    如果在一般图而不是二叉树上使用,请警告面试官你的例程可能会失败,进入无底、无止境的递归。

    【讨论】:

    • 这是蛮力的,但也是渐近最优的。在最坏的情况下,所有值都为零,请求的总和为零,并且必须枚举通过树的所有部分路径,所以你可以做的最好的就是蛮力。不过,可以利用结构共享来提高空间复杂度。
    【解决方案7】:

    可以将这棵树简化为加权图 G,其中每条边的权重 = 其每个节点中值的总和。

    然后,在图 G 上运行 Floyd-Warshall 算法。通过检查结果矩阵中的元素,我们可以获得总和等于所需总和的所有节点对。

    另外,请注意算法给出的最短路径也是这棵树中两个节点之间的唯一路径。

    这只是另一种方法,不如递归方法有效。

    【讨论】:

    • 你不应该在稀疏图上使用 Floyd-Warshall 算法。
    • @Thomash 我知道这不是最有效的,我在最后一句话中表达了这一点。我只是想展示一个可能的减少。通过这种减少,人们总是可以使用 Johnsons 算法来生成备用图。但是,我可能又一次陷入了让事情变得复杂的兔子洞。
    【解决方案8】:

    我们可以用树结构动态规划来解决,时间和空间复杂度都是O(n^2),其中n是所有树节点的个数。

    思路如下:

    对于树节点,我们保留一个集合,记录从 u 开始到其所有后代的所有可能和。然后递归地,任何节点的集合都可以由它的两个孩子更新,具体来说,通过合并两个孩子的集合。

    伪代码为:

    bool findPath(Node u, Set uset, int finalSum) {
        Set lset, rset;
        if (findPath(u.left, lset, finalSum) || findPath(u.right, rset, finalSum)) return true;
        for (int s1 : lset) {
            if (finalSum - u.val - s1 == 0 || rset.contains(finalSum - u.val - s1)) return true;
            // first condition means a path from u to some descendant in u's left child
            // second condition means a path from some node in u's left child to some node in u's right child
    
            uset.insert(s1 + u.val); // update u's set
        }
        for (int s2 : rset) {
            if (finalSum - u.val - s2 == 0) return true;
            // don't forget the path from u to some descendant in u's right child
            uset.insert(s2 + u.val); // update u's set
        }
        return false;
    }
    

    我注意到最初的问题是查找所有路径,但上面的算法是查找是否存在。我认为这个想法是相似的,但是这个版本使问题更容易解释:)

    【讨论】:

      【解决方案9】:
      public void printPath(N n) {
          printPath(n,n.parent);
      }
      
      private void printPath(N n, N endN) {
          if (n == null)
              return;
          if (n.left == null && n.right == null) {
              do {
                  System.out.print(n.value);
                  System.out.print(" ");
              } while ((n = n.parent)!=endN);
              System.out.println("");
              return;
          }
          printPath(n.left, endN);
          printPath(n.right, endN);
      }
      

      您可以打印树路径结束 n 节点。像这样 printPath(n);

      【讨论】:

        【解决方案10】:
        void printpath(int sum,int arr[],int level,struct node * root)
        {
          int tmp=sum,i;
          if(root == NULL)
          return;
          arr[level]=root->data;
          for(i=level;i>=0;i--)
          tmp-=arr[i];
          if(tmp == 0)
          print(arr,level,i+1);
          printpath(sum,arr,level+1,root->left);
          printpath(sum,arr,level+1,root->right);
        }
         void print(int arr[],int end,int start)
        {  
        
        int i;
        for(i=start;i<=end;i++)
        printf("%d ",arr[i]);
        printf("\n");
        }
        

        复杂度(n logn) 空间复杂度(n)

        【讨论】:

        • 你能解释一下时间复杂度是 O(nlogn) 吗?
        • 它不会打印所有路径...考虑下面的树(按顺序)并搜索 7 个总和...它将只返回一个路径:1 2 3 4 5 10 11 6 7 8 9 12 13 14 15
        【解决方案11】:
        # include<stdio.h>
        # include <stdlib.h>
        struct Node
        {
            int data;
            struct Node *left, *right;
        };
        
        struct Node * newNode(int item)
        {
            struct Node *temp =  (struct Node *)malloc(sizeof(struct Node));
            temp->data = item;
            temp->left =  NULL;
            temp->right = NULL;
            return temp;
        }
        void print(int p[], int level, int t){
            int i;
            for(i=t;i<=level;i++){
                printf("\n%d",p[i]);
            }
        }
        void check_paths_with_given_sum(struct Node * root, int da, int path[100], int level){
        
             if(root == NULL)
                return ;
            path[level]=root->data;
            int i;int temp=0;
            for(i=level;i>=0;i--){
                temp=temp+path[i];
                if(temp==da){
                    print(path,level,i);
                }
            }
                check_paths_with_given_sum(root->left, da, path,level+1);
                check_paths_with_given_sum(root->right, da, path,level+1);
        
        }
        int main(){
            int par[100];
         struct Node *root = newNode(10);
            root->left = newNode(2);
            root->right = newNode(4);
            root->left->left = newNode(1);
            root->right->right = newNode(5);
            check_paths_with_given_sum(root, 9, par,0);
        
        
        }
        

        这行得通.....

        【讨论】:

          【解决方案12】:

          https://codereview.stackexchange.com/questions/74957/find-all-the-paths-of-tree-that-add-to-a-input-value

          我已尝试回答,期待代码审查。我的代码和审阅者应该是有用的来源。

          【讨论】:

            【解决方案13】:

            以下是使用递归的解决方案。 我们执行二叉树的顺序遍历,当我们向下移动一个级别时,我们通过将当前级别的权重添加到树的先前级别的权重来总结总路径权重,如果我们达到我们的总和,我们然后打印出路。此解决方案将处理沿任何给定路径路径可能有多个解决方案的情况。

            假设你有一棵以根为根的二叉树。

            #include <iostream>
            #include <vector>
            using namespace std;
            
            class Node
            {
            private:
                Node* left;
                Node* right;
                int value;
            
            public:
                Node(const int value)
                {
                    left=NULL;
                    right=NULL;
                    this->value=value;
                }
            
                void setLeft(Node* left)
                {
                    this->left=left;
                }
            
                void setRight(Node* right)
                {
                    this->right = right;
                }
            
                Node* getLeft() const
                {
                    return left;
                }
            
                Node* getRight() const
                {
                    return right;
                }
            
                const int& getValue() const
                {
                    return value;
                }
            };
            
            //get maximum height of the tree so we know how much space to allocate for our
            //path vector
            
            int getMaxHeight(Node* root)
            {
                if (root == NULL)
                    return 0;
            
                int leftHeight = getMaxHeight(root->getLeft());
                int rightHeight = getMaxHeight(root->getRight());
            
                return max(leftHeight, rightHeight) + 1;
            }
            
            //found our target sum, output the path
            void printPaths(vector<int>& paths, int start, int end)
            {
                for(int i = start; i<=end; i++)
                    cerr<<paths[i]<< " ";
            
                cerr<<endl;
            }
            
            void generatePaths(Node* root, vector<int>& paths, int depth, const int sum)
            {
                //base case, empty tree, no path
                if( root == NULL)
                    return;
            
                paths[depth] = root->getValue();
                int total =0;
            
                //sum up the weights of the nodes in the path traversed
                //so far, if we hit our target, output the path
                for(int i = depth; i>=0; i--)
                {
                    total += paths[i];
                    if(total == sum)
                        printPaths(paths, i, depth);
                }
            
                //go down 1 level where we will then sum up from that level
                //back up the tree to see if any sub path hits our target sum
                generatePaths(root->getLeft(), paths, depth+1, sum);
                generatePaths(root->getRight(), paths, depth+1, sum);
            }
            
            int main(void)
            {
                vector<int> paths (getMaxHeight(&root));
                generatePaths(&root, paths, 0,0);
            }
            

            空间复杂度取决于树的高度,假设这是一棵平衡树,那么基于递归堆栈的深度,空间复杂度为 0(log n)。 时间复杂度 O(n Log n) - 基于平衡树,其中每个级别有 n 个节点,并且在每个级别将完成 n 工作量(对路径求和)。我们还知道平衡二叉树的树高以 O(log n) 为界,因此平衡二叉树上每个级别完成的工作量为 O(n log n)

            【讨论】:

              【解决方案14】:
              // assumption node have integer value other than zero
              void printAllPaths(Node root, int sum , ArrayList<Integer> path) {
              
                 if(sum == 0) {
                    print(path); // simply print the arraylist
                  }
              
                 if(root ==null) {
                   //traversed one end of the tree...just return
                    return;
                }
                  int data = root.data;
                  //this node can be at the start, end or in middle of path only if it is       //less than the sum
                  if(data<=sum) {
                   list.add(data);
                   //go left and right
                  printAllPaths(root.left, sum-data ,  path);
                  printAllPaths(root.right, sum-data ,  path);
              
                  }
                 //note it is not else condition to ensure root can start from anywhere
                 printAllPaths(root.left, sum ,  path);
                 printAllPaths(root.right, sum ,  path);
              }
              

              【讨论】:

                【解决方案15】:

                我改进了 Arvind Upadhyay 回答的一些编码逻辑。 一旦 if 循环完成,您就不能使用相同的列表。所以需要创建新的列表。 此外,需要保持逻辑从当前节点下降到搜索路径的级别计数。如果我们没有找到路径,那么在去它的孩子之前,我们需要从等于 count 次的递归调用中出来。

                int count =0;
                public void printAllPathWithSum(Node node, int sum, ArrayList<Integer> list)
                {   
                    if(node == null)
                        return;
                    if(node.data<=sum)
                    {
                        list.add(node.data);
                        if(node.data == sum)
                            print(list);
                        else
                        {
                            count ++;
                            printAllPathWithSum(node.left, sum-node.data, list);
                            printAllPathWithSum(node.right, sum-node.data, list);
                            count --;
                        }
                    }
                    if(count != 0)
                        return ;
                
                
                    printAllPathWithSum(node.left, this.sum, new ArrayList());
                    if(count != 0)
                        return;
                    printAllPathWithSum(node.right, this.sum, new ArrayList());
                
                }
                public void print(List list)
                {
                    System.out.println("Next path");
                    for(int i=0; i<list.size(); i++)
                        System.out.print(Integer.toString((Integer)list.get(i)) + " ");
                    System.out.println();
                }
                

                查看完整代码:https://github.com/ganeshzilpe/java/blob/master/Tree/BinarySearchTree.java

                【讨论】:

                  【解决方案16】:

                  搜索:

                  Recursively traverse the tree, comparing with the input key, as in binary search tree.
                  
                  If the key is found, move the target node (where the key was found) to the root position using splaysteps.
                  
                  Pseudocode:
                  
                  
                  Algorithm: search (key)
                  Input: a search-key
                  1.   found = false;
                  2.   node = recursiveSearch (root, key)
                  3.   if found
                  4.     Move node to root-position using splaysteps;
                  5.     return value
                  6.   else
                  7.     return null
                  8.   endif
                  Output: value corresponding to key, if found.
                  
                  
                  
                  Algorithm: recursiveSearch (node, key)
                  Input: tree node, search-key
                  1.   if key = node.key
                  2.     found = true
                  3.     return node
                  4.   endif
                       // Otherwise, traverse further 
                  5.   if key < node.key
                  6.     if node.left is null
                  7.       return node
                  8.     else
                  9.       return recursiveSearch (node.left, key)
                  10.    endif
                  11.  else
                  12.    if node.right is null
                  13.      return node
                  14.    else
                  15.      return recursiveSearch (node.right, key)
                  16.    endif
                  17.  endif
                  Output: pointer to node where found; if not found, pointer to node for insertion.
                  

                  【讨论】:

                    【解决方案17】:

                    因为我们需要 sum == k 的路径。 我假设最坏情况的复杂度可能是 O(total_paths_in_tree) 。

                    那么为什么不生成每条路径并检查总和,反正它是一棵有负数的树,甚至不是二叉搜索树。

                        struct node{
                          int val;
                          node *left,*right;
                    
                          node(int vl)
                          {
                            val = vl;
                            left = NULL;
                            right = NULL;
                          }
                       };
                    
                    
                       vector<vector<int> > all_paths;
                       vector<vector<int> > gen_paths(node* root)
                       {
                           if(root==NULL)
                           {
                              return vector<vector<int> > ();
                           }
                    
                           vector<vector<int> >    left_paths = gen_paths(root->left);
                           vector<vector<int> >    right_paths = gen_paths(root->right);
                    
                           left_paths.push_back(vector<int> ()); //empty path
                           right_paths.push_back(vector<int> ());
                    
                           vector<vector<int> > paths_here;
                           paths_here.clear();
                    
                    
                           for(int i=0;i<left_paths.size();i++)
                           {
                               for(int j=0;j<right_paths.size();j++)
                               {
                                  vector<int> vec;
                                  vec.clear();
                                  vec.insert(vec.end(), left_paths[i].begin(), left_paths[i].end());
                                 vec.push_back(root->val);
                                 vec.insert(vec.end(), right_paths[j].begin(), right_paths[j].end());
                                 paths_here.push_back(vec);
                               }
                            }
                    
                            all_paths.insert(all_paths.end(),paths_here.begin(),paths_here.end());
                    
                           vector<vector<int> > paths_to_extend;
                           paths_to_extend.clear();
                    
                           for(int i=0;i<left_paths.size();i++)
                           {
                                paths_to_extend.push_back(left_paths[i]);
                                paths_to_extend[i].push_back(root->val);
                           }
                    
                           for(int i=0;i<right_paths.size();i++)
                           {
                               paths_to_extend.push_back(right_paths[i]);
                               paths_to_extend[paths_to_extend.size()-1].push_back(root->val);
                           }
                    
                           return paths_to_extend;
                        }
                    

                    为了生成路径,我生成了所有左路径和所有右路径 并将 left_paths + node->val + right_paths 添加到每个节点的 all_paths 中。 并发送了仍然可以扩展的路径。即来自双方的所有路径+节点。

                    【讨论】:

                      【解决方案18】:

                      这是一个 O(N) 解决方案

                      int fn(root, sum, *count)                                                                               
                      {                                                                                                   
                          if(root == NULL)                                                                                
                              return 0;                                                                                                                                                                                       
                          int left =  fn(root->left, sum, count);                                                         
                      
                          int right = fn(root->left, sum, count);                                                                                                                                                            
                      
                          if(left == sum)                                                                                 
                              *count++;                                                                                   
                      
                          if(right == sum)                                                                                
                              *count++;                                                                                   
                      
                          if((root->data + left + right) == sum)                                                          
                              *count++;                                                                                   
                      
                          return (root->data + left + right);                                                             
                      }
                      

                      【讨论】:

                        猜你喜欢
                        • 2017-08-04
                        • 1970-01-01
                        • 1970-01-01
                        • 2018-03-04
                        • 2021-05-16
                        • 1970-01-01
                        • 2015-08-22
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多