AVL tree Height Method StackOverFlow Erroe - java

I am trying to implement AVL tree.I'm having stackOverFlow on height method. I tried with small number of inputs it works. However, When i tried with large scale of input, it crush. Here is my code.
private int height(Node<T> node){
if(!isEmpty() && node != null){
if(isleaf(node))
return 1;
else{
int p = height(node.left);
int q = height(node.right);
if(p > q)
return p + 1;
else
return q + 1;
}
}
return 0;
}

This can happen if your tree has cyclic references. Check tree construction. To debug - assign unique values and print while traversing the nodes.

Related

Implementing Union-Find Algorithm for Kruskal's Algorithm to find Minimum Spanning Tree in Java

I am trying to solve the following Leetcode problem (https://leetcode.com/problems/connecting-cities-with-minimum-cost), and my approach is to figure out the total weight of the minimum spanning tree (MST) from the input graph using Kruskal's Algorithm using the Union-Find data structure. However, my code online passes 51/63 of the test cases, returning the incorrect result on the following test case, which is too hard to debug, since the input graph is too large.
50
[[2,1,22135],[3,1,13746],[4,3,37060],[5,2,48513],[6,3,49607],[7,1,97197],[8,2,95909],[9,2,82668],[10,2,48372],[11,4,17775],[12,2,6017],[13,1,51409],[14,2,12884],[15,7,98902],[16,14,52361],[17,8,11588],[18,12,86814],[19,17,49581],[20,4,41808],[21,11,77039],[22,10,80279],[23,16,61659],[24,12,89390],[25,24,10042],[26,12,78278],[27,15,30756],[28,6,2883],[29,8,3478],[30,7,29321],[31,12,47542],[32,20,35806],[33,3,26531],[34,12,16321],[35,27,82484],[36,7,55920],[37,24,21253],[38,23,90537],[39,7,83795],[40,36,70353],[41,34,76983],[42,14,63416],[43,15,39590],[44,9,86794],[45,3,31968],[46,19,32695],[47,17,40287],[48,1,27993],[49,12,86349],[50,11,52080],[17,27,65829],[42,45,87517],[14,23,96130],[5,50,3601],[10,17,2017],[26,44,4118],[26,29,93146],[1,9,56934],[22,43,5984],[3,22,13404],[13,28,66475],[11,14,93296],[16,44,71637],[7,37,88398],[7,29,56056],[2,34,79170],[40,44,55496],[35,46,14494],[32,34,25143],[28,36,59961],[10,49,58317],[8,38,33783],[8,28,19762],[34,41,69590],[27,37,26831],[15,23,53060],[5,11,7570],[20,42,98814],[18,34,96014],[13,43,94702],[1,46,18873],[44,45,43666],[22,40,69729],[4,25,28548],[8,46,19305],[15,22,39749],[33,48,43826],[14,15,38867],[13,22,56073],[3,46,51377],[13,15,73530],[6,36,67511],[27,38,76774],[6,21,21673],[28,49,72219],[40,50,9568],[31,37,66173],[14,29,93641],[4,40,87301],[18,46,41318],[2,8,25717],[1,7,3006],[9,22,85003],[14,45,33961],[18,28,56248],[1,31,10007],[3,24,23971],[6,28,24448],[35,39,87474],[10,50,3371],[7,18,26351],[19,41,86238],[3,8,73207],[11,34,75438],[3,47,35394],[27,32,69991],[6,40,87955],[2,18,85693],[5,37,50456],[8,20,59182],[16,38,58363],[9,39,58494],[39,43,73017],[10,15,88526],[16,23,48361],[4,28,59995],[2,3,66426],[6,17,29387],[15,38,80738],[12,43,63014],[9,11,90635],[12,20,36051],[13,25,1515],[32,40,72665],[10,40,85644],[13,40,70642],[12,24,88771],[14,46,79583],[30,49,45432],[21,34,95097],[25,48,96934],[2,35,79611],[9,26,71147],[11,37,57109],[35,36,67266],[42,43,15913],[3,30,44704],[4,32,46266],[5,10,94508],[31,39,45742],[12,25,56618],[10,45,79396],[15,28,78005],[19,32,94010],[36,46,4417],[6,35,7762],[10,13,12161],[49,50,60013],[20,23,6891],[9,50,63893],[35,43,74832],[10,24,3562],[6,8,47831],[29,32,82689],[7,47,71961],[14,41,82402],[20,33,38732],[16,26,24131],[17,34,96267],[21,46,81067],[19,47,41426],[13,24,68768],[1,25,78243],[2,27,77645],[11,25,96335],[31,45,30726],[43,44,34801],[3,42,22953],[12,23,34898],[37,43,32324],[18,44,18539],[8,13,59737],[28,37,67994],[13,14,25013],[22,41,25671],[1,6,57657],[8,11,83932],[42,48,24122],[4,15,851],[9,29,70508],[7,32,53629],[3,4,34945],[2,32,64478],[7,30,75022],[14,19,55721],[20,22,84838],[22,25,6103],[8,49,11497],[11,32,22278],[35,44,56616],[12,49,18681],[18,43,56358],[24,43,13360],[24,47,59846],[28,43,36311],[17,25,63309],[1,14,30207],[39,48,22241],[13,26,94146],[4,33,62994],[40,48,32450],[8,19,8063],[20,29,56772],[10,27,21224],[24,30,40328],[44,46,48426],[22,45,39752],[6,43,96892],[2,30,73566],[26,36,43360],[34,36,51956],[18,20,5710],[7,22,72496],[3,39,9207],[15,30,39474],[11,35,82661],[12,50,84860],[14,26,25992],[16,39,33166],[25,41,11721],[19,40,68623],[27,28,98119],[19,43,3644],[8,16,84611],[33,42,52972],[29,36,60307],[9,36,44224],[9,48,89857],[25,26,21705],[29,33,12562],[5,34,32209],[9,16,26285],[22,37,80956],[18,35,51968],[37,49,36399],[18,42,37774],[1,30,24687],[23,43,55470],[6,47,69677],[21,39,6826],[15,24,38561]]
I'm having trouble understanding why my code will fail a test case, since I believe I am implementing the steps of Kruskal's Algorithm propertly:
Sorting the connections in increasing order of weight.
Building the MST by going through each connection in the sorted list and selecting that connection if it does not result in a cycle in the MST.
Below is my Java code:
class UnionFind {
// parents[i] = parent node of node i.
// If a node is the root node of a component, we define its parent
// to be itself.
int[] parents;
public UnionFind(int n) {
this.parents = new int[n];
for (int i = 0; i < n; i++) {
this.parents[i] = i;
}
}
// Merges two nodes into the same component.
public void union(int node1, int node2) {
int node1Component = find(node1);
int node2Component = find(node2);
this.parents[node1Component] = node2Component;
}
// Returns the component that a node is in.
public int find(int node) {
while (this.parents[node] != node) {
node = this.parents[node];
}
return node;
}
}
class Solution {
public int minimumCost(int n, int[][] connections) {
UnionFind uf = new UnionFind(n + 1);
// Sort edges by increasing cost.
Arrays.sort(connections, new Comparator<int[]>() {
#Override
public int compare(final int[] a1, final int[] a2) {
return a1[2] - a2[2];
}
});
int edgeCount = 0;
int connectionIndex = 0;
int weight = 0;
// Greedy algorithm: Choose the edge with the smallest weight
// which does not form a cycle. We know that an edge between
// two nodes will result in a cycle if those nodes are already
// in the same component.
for (int i = 0; i < connections.length; i++) {
int[] connection = connections[i];
int nodeAComponent = uf.find(connection[0]);
int nodeBComponent = uf.find(connection[1]);
if (nodeAComponent != nodeBComponent) {
weight += connection[2];
edgeCount++;
}
if (edgeCount == n - 1) {
break;
}
}
// MST, by definition, must have (n - 1) edges.
if (edgeCount == n - 1) {
return weight;
}
return -1;
}
}
As #geobreze stated, I forgot to unite the components (disjoint sets) of node A and node B. Below is the corrected code:
if (nodeAComponent != nodeBComponent) {
uf.union(nodeAComponent, nodeBComponent);
weight += connection[2];
edgeCount++;
}

Solution timing out for question: build binary tree from inorder and postorder

I've been grinding leetcode recently and am perplexed on why my solution is timing out when I submit it to Leetcode.
Here is the question:
https://leetcode.com/explore/learn/card/data-structure-tree/133/conclusion/942/
Given inorder and postorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
For example, given
inorder = [9,3,15,20,7]
postorder = [9,15,7,20,3]
Return the following binary tree:
3
/ \
9 20
/ \
15 7
Here is my solution that times out in one of the test cases:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (inorder == null || inorder.length == 0) {
return null; // input error
}
if (postorder == null || postorder.length == 0) {
return null; // input error
}
if (postorder.length != inorder.length) {
return null; // input error
}
List<Integer> inOrder = new ArrayList<Integer>();
List<Integer> postOrder = new ArrayList<Integer>();
for (int i = 0; i < inorder.length; i++) {
inOrder.add(inorder[i]);
postOrder.add(postorder[i]);
}
return buildBinaryTree(inOrder, postOrder);
}
public TreeNode buildBinaryTree(List<Integer> inOrder, List<Integer> postOrder) {
boolean found = false;
int root = 0;
int rootIndex = 0;
// for given in-order scan the post-order right to left to find the root
for (int j = postOrder.size() - 1; j >= 0 && !found; j--) {
root = postOrder.get(j);
if (inOrder.contains(root)) {
rootIndex = inOrder.indexOf(root);
root = inOrder.get(rootIndex);
found = true;
break;
}
}
if (found) {
List<Integer> leftOfRoot = new ArrayList<Integer>();
List<Integer> rightOfRoot = new ArrayList<Integer>();
if (rootIndex > 0) {
leftOfRoot.addAll(inOrder.subList(0, rootIndex));
}
if ((rootIndex + 1) < inOrder.size()) {
rightOfRoot.addAll(inOrder.subList(rootIndex + 1, inOrder.size()));
}
TreeNode node = new TreeNode(root);
node.left = buildBinaryTree(leftOfRoot, postOrder);
node.right = buildBinaryTree(rightOfRoot, postOrder);
return node;
}
return null;
}
}
Can anyone help determine why this is happening? I'm thinking it is the Leetcode judge at fault here and my code is fine.
Leetcode's judge is probably OK. This code is too casual about nested linear array operations and heap allocations. Creating ArrayLists and calling contains, addAll, subList and indexOf may appear innocuous, but they should all be thought of as extremely expensive operations when inside a recursive function that spawns two child calls in every frame.
Let's unpack the code a bit:
List<Integer> inOrder = new ArrayList<Integer>();
List<Integer> postOrder = new ArrayList<Integer>();
for (int i = 0; i < inorder.length; i++) {
inOrder.add(inorder[i]);
postOrder.add(postorder[i]);
}
This is a minor up-front cost but it's an omen of things to come. We've done 2 heap allocations that weren't necessary and walked n. I'd stick to primitive arrays here--no need to allocate objects other than the result nodes. A lookup map for inOrder with value -> index pairs might be useful to allocate if you feel compelled to create a supporting data structure here.
Next, we step into buildBinaryTree. Its structure is basically:
function buildBinaryTree(root) {
// do some stuff
if (not base case reached) {
buildBinaryTree(root.left)
buildBinaryTree(root.right)
}
}
This is linear on the number of nodes in the tree, so it's important that // do some stuff is efficient, hopefully constant time. Walking n in this function would give us quadratic complexity.
Next there's
for (int j = postOrder.size() - 1; j >= 0 && !found; j--) {
root = postOrder.get(j);
if (inOrder.contains(root)) {
rootIndex = inOrder.indexOf(root);
This looks bad, but by definition the root is always the last element in a postorder traversal array, so if we keep a pointer to it, we can remove this outer loop. You can use indexOf directly and avoid the contains call since indexOf returns -1 to indicate a failed search.
The code:
if (found) {
List<Integer> leftOfRoot = new ArrayList<Integer>();
List<Integer> rightOfRoot = new ArrayList<Integer>();
does more unnecessary heap allocations for every call frame.
Here,
leftOfRoot.addAll(inOrder.subList(0, rootIndex));
Walks the list twice, once to create the sublist and again to add the entire sublist to the ArrayList. Repeat for the right subtree for two full walks on n per frame. Using start and end indices per call frame means you never need to allocate heap memory or copy anything to prepare the next call. Adjust the indices and pass a reference to the same two arrays along the entire time.
I recommend running your code with a profiler to see exactly how much time is spent copying and scanning your ArrayLists. The correct implementation should do at most one walk through one of the lists per call frame to locate root in inOrder. No array copying should be done at all.
With these modifications, you should be able to pass, although wrangling the pointers for this problem is not obvious. A hint that may help is this: recursively process the right subtree before the left.
Yes, it would be much faster with arrays. Try this:
public static TreeNode buildTree(int[] inorder, int[] postorder, int start,
int end) {
for (int i = postorder.length-1; i >= 0; --i) {
int root = postorder[i];
int index = indexOf(inorder, start, end, root);
if (index >= 0) {
TreeNode left = index == start
? null
: buildTree(inorder, postorder, start, index);
TreeNode right = index+1 == end
? null
: buildTree(inorder, postorder, index+1, end);
return new TreeNode(root, left, right);
}
}
return null;
}
private static int indexOf(int[] array, int start, int end, int value) {
for (int i = start; i < end; ++i) {
if (array[i] == value) {
return i;
}
}
return -1;
}

Walk tree data structure to find its height and count elements in one loop

I have a tree structure.
class Element {
private List<Element> children;
}
Element treeStructure = produceSomeTreeStructure();
//How to get its height and number of elements.
Straight-forward solution is to make two loops. In first I can find number of nodes
A question on getting number of nodes in a Binary Tree
(change this algorithm for non-binary tree),
and the second loop to get the tree's height
http://www.geeksforgeeks.org/iterative-method-to-find-height-of-binary-tree/
Again, adapt this algorithm to non-binary tree.
My question, how to do this in one walk. It is acceptable for me to keep results in global variables.
If you want to know the number of nodes, then you'll need to explore the whole tree. The easiest way to do this is with a depth-first search, where you count the nodes as you go.
A depth-first search algorithm can also easily enough count the depth to which it's currently exploring, and the maximum depth reached overall. Modify the depth-first search algorithm to take both of these as arguments.
If you code it recursively (easiest), then you can simply add one to the depth argument every time you make a recursive call. And if this gives you a number that's greater than the maximum that you're keeping track of, then update the maximum to the current depth.
Yes that can be done as it is shown in the below code. Just add the counter totalNodeCount and do +1 each time you traverse a node in BFS style.
// Iterative method to find height and node-count of Binary Tree
int treeHeightAndNumOfNodes(node *root)
{
// Base Case
if (root == NULL)
return 0;
// Create an empty queue for level order tarversal
queue<node *> q;
// Enqueue Root and initialize height
q.push(root);
int height = 0;
int totalNodeCount = 0; // <-- Use this counter to store total number of node traversed.
while (1)
{
// nodeCount (queue size) indicates number of nodes
// at current lelvel.
int nodeCount = q.size();
if (nodeCount == 0)
return height;
height++;
// Dequeue all nodes of current level and Enqueue all
// nodes of next level
while (nodeCount > 0)
{
node *node = q.front();
q.pop();
if (node->left != NULL)
q.push(node->left);
if (node->right != NULL)
q.push(node->right);
nodeCount--;
totalNodeCount++; // <-- Update this counter
}
}
}
Again, adapt this algorithm to non-binary tree.
To do that, replace the given below lines of codes with a loop that traverse through each child nodes and push the NON-NULL children into queue.
if (node->left != NULL)
q.push(node->left);
if (node->right != NULL)
q.push(node->right);
What you are looking for is a bit like a BFS. You just have to walk your tree like the following:
int getHeight(Element e) {
int max_height = 0;
for (Element child : e.children) {
max_height = max(max_height, getHeight(child));
}
return max_height + 1;
}
Similarly, getting the total number of elements is easy: instead of getting the maximum value among the node's children, you just add them up.
int getTotalCount(Element e) {
int total_count = 0;
for (Element child : e.children) {
total_count += getTotalCount(el);
}
return total_count + 1;
}
If you must return the two numbers using the same function, just pack them in a common class to traverse your tree only once.
Thanks guys for your answers.
And this is what I have coded.
public static TreeData countElementsAndFindHeight(Element root) {
TreeData treePair = new TreeData();
if (root == null) {
return treePair;
}
treePair.nElements = 1;
treePair.height = 1;
//Nodes queue will contain all the elements of the trees, so its size is the number of elements.
List<Element> nodesQueue = new LinkedList<Element>();
treePair.walkedNodes = nodesQueue;
List<Element> children = root.getChildren();
if (CommonUtils.isCollectionEmpty(children)) {
return treePair;
}
treePair.height = countElementsAndFindHeight(root, nodesQueue);
nodesQueue.add(root);
treePair.nElements = nodesQueue.size();
return treePair;
}
private static int countElementsAndFindHeight(Element root, List<Element> nodesQueue) {
int maxHeight = 1;
List<Element> children = root.getChildren();
if (CommonUtils.isCollectionEmpty(children)) {
return maxHeight;
}
for (Element childElement : children) {
int childHeight = countElementsAndFindHeight(childElement, nodesQueue);
if (childHeight > maxHeight) {
maxHeight = childHeight;
}
nodesQueue.add(childElement);
}
return maxHeight + 1;
}
public static class TreeData {
protected int height = 0;
protected int nElements = 0;
}

Find numbers of nodes between root and give node

So in a given binary tree (node binary search tree), initially I want to find the number of nodes between two nodes "p" and "q". I first find the lowest common ancestor between these two nodes, say, "ancestor". Then I calculate the number of nodes between "ancestor" and "p" and number of nodes between "ancestor" and "q" separately and add them at last.
I tried recursive way to get number of nodes between "ancestor" and "p" or "q" but failed. Not a fan of recursive.
public static int NodeToNodePath(BinaryTree root, BinaryTree node, int length){
if(root == null && node == null)
return 0;
if(root == null || node == null)
return 0;
if(root.rootElement == node.rootElement){
return length;
}
int sum = NodeToNodePath(root.left, node, length + 1);
if(sum != 0)
return sum;
sum = NodeToNodePath(root.right, node, sum);
return sum;
}
But in this way, the result from root to left mode is correct but can't find node on the other size.
Any help?
Thanks!
I figure out how to solve the problem. By recursion. This may not apply to my origin problem
"find node number between two given nodes" but it does return number of nodes between root and a given node.
Code is posted below.
public static int NodeToNodePath(BinaryTree root,
BinaryTree node, int length) {
if(root == null)
return 0;
if(root.rootElement == node.rootElement){
length += 1;
return length;
}
int left = NodeToNodePath(root.left, node, length);
if(left != 0){
return left + 1;
}
int right = NodeToNodePath(root.right, node, length);
if(right != 0){
return right + 1;
}
return 0;
}
Also, I found a post on GeekForGeeks talking specifically about my origin problem, it's called "Find distance between two given keys of a Binary Tree" the address is:
http://www.geeksforgeeks.org/find-distance-two-given-nodes/
Thanks everyone!

How to stop recursion after returning from method

I have a program which makes call to a functin which is recursive.
int dd=dis(root,2,0);
Function code
public int dis(Node n,int g,int count)
{
if(g==n.data)
{
System.out.println("equal count"+count);
return count;
}
else if(g>n.data)
{
count=count+1;
dis(n.right,g,count);
}
else if(g<n.data)
{
count=count+1;
dis(n.left,g,count);
}
System.out.println("function"+count);
return count;
}
When the data equals node value, the function returns count, the exact value I needed. However, the recursion continues after count is returned, and returns the abnormal count value at the end of function.
I want to totally back out of the function after count is returned from == case, I dont want recursion to modify the value in the calling function after first count has been returned.
Change this:
dis(n.right,g,count);
to this:
return dis(n.right,g,count);
and this:
dis(n.left,g,count);
to this:
return dis(n.left,g,count);
Edited to add: A simpler way to write this function might be:
public int dis(final Node n, final int g)
{
if(g == n.data)
return 0;
else
return 1 + dis(g < n.data ? n.left : n.right, g);
}
Note that in this approach, the count variable completely disappears: from an imperative/procedural standpoint, you might say that rather than counting the nodes as you descend into the tree, this approach counts them as it returns back out. (But it's better to look at it from a functional/recursive standpoint, and say that if the depth of g in the appropriate subtree is n, then its depth in the parent tree is one greater.)
The simplest imperative version is probably:
public int dis(final Node root, final int g)
{
int depth = 0;
for(Node n = root; g != n.data; n = (g < n.data ? n.left : n.right))
++depth;
return depth;
}

Categories