Algorithm to print all paths with a given sum in a binary tree

后端 未结 18 1303
既然无缘
既然无缘 2020-12-24 07:04

The following is an interview question.

You are given a binary tree (not necessarily BST) in which each node contains a value. Design an algorithm t

相关标签:
18条回答
  • 2020-12-24 07:24

    Search:

    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.
    
    0 讨论(0)
  • 2020-12-24 07:27
    // 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);
    }
    
    0 讨论(0)
  • 2020-12-24 07:28

    Update: I see now that my answer does not directly answer your question. I will leave it here if it proves useful, but it needs no upvotes. If not useful, I'll remove it. I do agree with @nhahtdh, however, when he advises, "Reuse your algorithm with all other nodes as root."

    One suspects that the interviewer is fishing for recursion here. Don't disappoint him!

    Given a node, your routine should call itself against each of its child nodes, if it has any, and then add the node's own datum to the return values, then return the sum.

    For extra credit, warn the interviewer that your routine can fail, entering an bottomless, endless recursion, if used on a general graph rather than a binary tree.

    0 讨论(0)
  • 2020-12-24 07:28

    We can solve it with tree-structure dynamic programming, and both the time and space complexity is O(n^2), where n is the number of all the tree nodes.

    The idea is as follows:

    For a tree node, we keep a set recording all possible sums starting from u to its all descendants. Then recursively, any node's set can be updated by its two children, specifically, by merging two children's sets.

    The pseudocode is:

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

    I notice the original question is to find all paths, but the algorithm above is to find whether existed. I think the idea is similar, but this version makes the problem easier to explain :)

    0 讨论(0)
  • 2020-12-24 07:35

    A clean solution in JAVA. Using internal recursive calls keeping track of the traversed paths.

    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;
    }
    
    0 讨论(0)
  • 2020-12-24 07:36

    I have improved some coding logic of answer by Arvind Upadhyay. Once the if loop done, you can not use the same list. So need to create the new list. Also, there is need to maintain count of level the logic go down for from current node to search path. If we do not find path, so before going to its children, we need to come out from the recursive call equal to count times.

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

    Check the full code at: https://github.com/ganeshzilpe/java/blob/master/Tree/BinarySearchTree.java

    0 讨论(0)
提交回复
热议问题