Non-binary Tree Height (Optimization)

Question:

Introduction

So I’m doing a course on edX and have been working on this practice assignment for
the better part of 3 hours, yet I still can’t find a way to implement this method
without it taking to long and timing out the automatic grader.

I’ve tried 3 different methods all of which did the same thing.
Including 2 recursive approaches and 1 non-recursive approach (my latest).

The problem I think I’m having with my code is that the method to find children just takes way to long because it has to iterate over the entire list of nodes.

Input and output format

Input includes N on the first line which is the size of the list which is given on line 2.

Example:

5
-1 0 4 0 3

To build a tree from this:
Each of the values in the array are a pointer to another index in the array such that in the example above 0 is a child node of -1 (index 0). Since -1 points to no other index it is the root node.

The tree in the example has the root node -1, which has two children 0 (index 1) and 0 (index 3). The 0 with index 1 has no children and the 0 with index 3 has 1 child: 3 (index 4) which in turn has only one child which is 4 (index 2).

The output resulting from the above input is 4. This is because the max height of the branch which included -1 (the root node), 0, 3, and 4 was of height 4 compared to the height of the other branch (-1, and 0) which was height 2.

If you need more elaborate explanation then I can give another example in the comments!

The output is the max height of the tree. The size of the input goes up to 100,000 which was where I was having trouble as it has to do that it in exactly 3 seconds or under.

My code

Here’s my latest non-recursive method which I think is the fastest I’ve made (still not fast enough). I used the starter from the website which I will also include beneath my code. Anyways, thanks for the help!

My code:

# python3

import sys, threading
sys.setrecursionlimit(10**7) # max depth of recursion
threading.stack_size(2**27)  # new thread will get stack of such size

def height(node, parent_list):
        h = 0
        while not node == -1:
                h = h + 1
                node = parent_list[node]
        return h + 1

def search_bottom_nodes(parent_list):
        bottom_nodes = []
        for index, value in enumerate(parent_list):
                children = [i for i, x in enumerate(parent_list) if x == index]
                if len(children) == 0:
                        bottom_nodes.append(value)

        return bottom_nodes

class TreeHeight:
        def read(self):
                self.n = int(sys.stdin.readline())
                self.parent = list(map(int, sys.stdin.readline().split()))

        def compute_height(self):
                # Replace this code with a faster implementation
                bottom_nodes = search_bottom_nodes(self.parent)
                h = 0
                for index, value in enumerate(bottom_nodes):
                        h = max(height(value, self.parent), h)
                return h


def main():
  tree = TreeHeight()
  tree.read()
  print(tree.compute_height())

threading.Thread(target=main).start()

edX starter:

# python3

import sys, threading
sys.setrecursionlimit(10**7) # max depth of recursion
threading.stack_size(2**27)  # new thread will get stack of such size

class TreeHeight:
        def read(self):
                self.n = int(sys.stdin.readline())
                self.parent = list(map(int, sys.stdin.readline().split()))

        def compute_height(self):
                # Replace this code with a faster implementation
                maxHeight = 0
                for vertex in range(self.n):
                        height = 0
                        i = vertex
                        while i != -1:
                                height += 1
                                i = self.parent[i]
                        maxHeight = max(maxHeight, height);
                return maxHeight;

def main():
  tree = TreeHeight()
  tree.read()
  print(tree.compute_height())

threading.Thread(target=main).start()
Asked By: macklin wilson

||

Answers:

Simply cache the previously computed heights of the nodes you’ve traversed through in a dict and reuse them when they are referenced as parents.

import sys, threading
sys.setrecursionlimit(10**7) # max depth of recursion
threading.stack_size(2**27)  # new thread will get stack of such size

class TreeHeight:
    def height(self, node):
        if node == -1:
            return 0
        if self.parent[node] in self.heights:
            self.heights[node] = self.heights[self.parent[node]] + 1
        else:
            self.heights[node] = self.height(self.parent[node]) + 1
        return self.heights[node]

    def read(self):
        self.n = int(sys.stdin.readline())
        self.parent = list(map(int, sys.stdin.readline().split()))
        self.heights = {}

    def compute_height(self):
        maxHeight = 0
        for vertex in range(self.n):
            maxHeight = max(maxHeight, self.height(vertex))
        return maxHeight;

def main():
    tree = TreeHeight()
    tree.read()
    print(tree.compute_height())

threading.Thread(target=main).start()

Given the same input from your question, this (and your original code) outputs:

4
Answered By: blhsing
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.