-1

Given an N-ary tree, I have to generate all the leaf to leaf paths in an n-array tree. The path should also denote the direction. As an example:

Tree:

               1
            /     \
          2        6
        /   \
       3     4
      /
     5  

Paths:

  • 5 UP 3 UP 2 DOWN 4
  • 4 UP 2 UP 1 DOWN 6
  • 5 UP 3 UP 2 UP 1 DOWN 6

These paths can be in any order, but all paths need to be generated.

I kind of see the pattern:

  • looks like I have to do in order traversal and
  • need to save what I have seen so far.

However, can't really come up with an actual working algorithm.

Can anyone nudge me to the correct algorithm?

I am not looking for the actual implementation, just the pseudo code and the conceptual idea would be much appreciated.

Exploring
  • 2,493
  • 11
  • 56
  • 97

2 Answers2

0

The first thing I would do is to perform in-order traversal. As a result of this, we will accumulate all the leaves in the order from the leftmost to the rightmost nodes.(in you case this would be [5,4,6]) Along the way, I would certainly find the mapping between nodes and its parents so that we can perform dfs later. We can keep this mapping in HashMap(or its analogue). Apart from this, we will need to have the mapping between nodes and its priorities which we can compute from the result of the in-order traversal. In your example the in-order would be [5,3,2,4,1,6] and the list of priorities would be [0,1,2,3,4,5] respectively.

Here I assume that our node looks like(we may not have the mapping node -> parent a priori):

class TreeNode {
    int val;
    TreeNode[] nodes;

    TreeNode(int x) {
        val = x;
    }
}

If we have n leaves, then we need to find n * (n - 1) / 2 paths. Obviously, if we have managed to find a path from leaf A to leaf B, then we can easily calculate the path from B to A. (by transforming UP -> DOWN and vice versa)

Then we start traversing over the array of leaves we computed earlier. For each leaf in the array we should be looking for paths to leaves which are situated to the right of the current one. (since we have already found the paths from the leftmost nodes to the current leaf)

To perform the dfs search, we should be going upwards and for each encountered node check whether we can go to its children. We should NOT go to a child whose priority is less than the priority of the current leaf. (doing so will lead us to the paths we already have) In addition to this, we should not visit nodes we have already visited along the way.

As we are performing dfs from some node, we can maintain a certain structure to keep the nodes(for instance, StringBuilder if you program in Java) we have come across so far. In our case, if we have reached leaf 4 from leaf 5, we accumulate the path = 5 UP 3 UP 2 DOWN 4. Since we have reached a leaf, we can discard the last visited node and proceed with dfs and the path = 5 UP 3 UP 2.

There might be a more advanced technique for solving this problem, but I think it is a good starting point. I hope this approach will help you out.

g-alkilani
  • 161
  • 6
0

I didn't manage to create a solution without programming it out in Python. UNDER THE ASSUMPTION that I didn't overlook a corner case, my attempt goes like this:

In a depth-first search every node receives the down-paths, emits them (plus itself) if the node is a leaf or passes the down-paths to its children - the only thing to consider is that a leaf node is a starting point of a up-path, so these are input from the left to right children as well as returned to the parent node.

def print_leaf2leaf(root, path_down):
    for st in path_down:
        st.append(root)
    if all([x is None for x in root.children]):
        for st in path_down:
            for n in st: print(n.d,end=" ")
            print()
        path_up = [[root]]
    else:
        path_up = []
        for child in root.children:
            path_up += child is not None and [st+[root] for st in print_root2root(child, path_down + path_up)] or []
    for st in path_down:
        st.pop()
    return path_up

class node:
    def __init__(self,d,*children):
        self.d = d
        self.children = children
    
##               1
##            /     \
##          2         6
##        /   \      /
##       3     4     7
##      /          / | \
##     5          8  9  10
five = node(5)
three = node(3,five)
four = node(4)
two = node(2,three,four)
eight = node(8)
nine = node(9)
ten = node(10)
seven = node(7,eight,nine,ten)
six = node(6,None,seven)
one = node(1,two,six)

print_leaf2leaf(one,[])
Vroomfondel
  • 2,704
  • 1
  • 15
  • 29