Finding the mode in Binary Search Tree - algorithm

I saw this question has been around on this site, but I would like to discuss one issue please about tracking prev value in the code below. Given the following solution for finding the Mode in binary search tree,
class Solution {
Integer prev = null;
int count = 1;
int max = 0;
public int[] findMode(TreeNode root) {
//this is expandable, but int [] array is not expandable
List<Integer> modes = new ArrayList();
traverse(root, modes);
int[] result = new int[modes.size()];
for (int i=0; i<modes.size(); i++){
result[i] = modes.get(i);
}
return result;
}
//In BST, do inorder since that way nodes will be sorted L < root < R
public void traverse(TreeNode root, List<Integer> modes){
if(root == null) return; //dont do anything
traverse(root.left, modes);
if(prev != null){
if(prev == root.val){
count ++;
} else{
count =1;
}
}
if(count > max){
max = count;
modes.clear(); //delete all previous modes as we find a new one
modes.add(root.val);
} else if(count == max) { // we find another mode that has same # of occurrences
modes.add(root.val);
}
prev = root.val;
traverse( root.right, modes);
}
}
Now, the prev variable is supposed to capture the previous node value so that when we enter to node's left child as the code show, we will immediately compare it to left child of that node. For example, if prev = 5, then once we go up to 10, the new prev is prev = root.val;, then we got to 15 the right child of 10. But we don't compare prev to 15, but to 10 as we immediately go left in the code once, so we compare prev = 10 to node.val in if(prev == root.val) line. We go from there for all other nodes.
Problem: Suppose the node that is immediately left to 30 is 25 and not 20, then the trick used in this solution won't work in this case, what do you think pleas?

The algorithm is performing an in-order tree traversal, which does this:
traverse the left subtree by recursively calling the in-order function.
access the data part of the current node.
traverse the right subtree by recursively calling the in-order function.
In a binary search tree, because of the order of the nodes, an in-order traversal is visiting the nodes in ascending sorted order.
I think this picture (courtesy Wikipedia) will help to explain what's happening:
In-order traversal will visit the nodes in this order:
A, B, C, D, E, F, G, H, I;
Now since we are visiting the nodes is ascending sorted order, duplicates will be grouped together. Therefore, we just need to compare the current node with the previous node to find duplicates.
In your first example tree, the nodes are visited in this order:
5, 10, 10, 12, 15, 15, 16, 18, 20, 20, 20, 20, 25, 28, 30, 32.
The mode is 20.
In your second example tree, the nodes are visited in this order:
5, 10, 10, 12, 15, 15, 16, 18, 20, 20, 20, 25, 30, 32.
The mode is 20.

Related

Construct binary tree given its inorder and preorder traversals without recursion

Given inorder and preorder traversals of a tree, how the tree can be re-constructed in non-recursive manner.
For example:
Re-construct the following tree
1
2 3
4 5 6 7
8 9
given
inorder traversal: 4, 2, 5, 8, 1, 6, 3, 9, 7
preorder traversal: 1, 2, 4, 5, 8, 3, 6, 7, 9
Note: There are many references to recursive implementations. For example, one may refer Construct Tree from given Inorder and Preorder traversals. However intent here is to find non-recursive implementation.
Idea is to keep tree nodes in a stack from preorder traversal, till their counterpart is not found in inorder traversal. Once a counterpart is found, all children in the left sub-tree of the node must have been already visited.
Following is non-recursive Java implementation.
public TreeNode constructTree(int[] preOrder, int[] inOrder) {
if (preOrder.length == 0) {
return null;
}
int preOrderIndex = 0;
int inOrderIndex = 0;
ArrayDeque<TreeNode> stack = new ArrayDeque<>();
TreeNode root = new TreeNode(preOrder[0]);
stack.addFirst(root);
preOrderIndex++;
while (!stack.isEmpty()) {
TreeNode top = stack.peekFirst();
if (top.val == inOrder[inOrderIndex]) {
stack.pollFirst();
inOrderIndex++;
// if all the elements in inOrder have been visted, we are done
if (inOrderIndex == inOrder.length) {
break;
}
// Check if there are still some unvisited nodes in the left
// sub-tree of the top node in the stack
if (!stack.isEmpty()
&& stack.peekFirst().val == inOrder[inOrderIndex]) {
continue;
}
// As top node in stack, still has not encontered its counterpart
// in inOrder, so next element in preOrder must be right child of
// the removed node
TreeNode node = new TreeNode(preOrder[preOrderIndex]);
preOrderIndex++;
top.right = node;
stack.addFirst(node);
} else {
// Top node in the stack has not encountered its counterpart
// in inOrder, so next element in preOrder must be left child
// of this node
TreeNode node = new TreeNode(preOrder[preOrderIndex]);
preOrderIndex++;
top.left = node;
stack.addFirst(node);
}
}
return root;
}

Get Main Line From Graph

I am Facing a problem that requires some sort of an algorithm which allows me to get main line from a graph. A main line is basically a feeder network. On a graph it would be the main nodes that feeds sub nodes. Picture below explains.
so the main line in the diagram above would be 1, 2, 3, 4, 5. Each node contains a property which is the list of connected nodes; So number 3 would contain 2, 4, and 10. I started thinking that first I should get rid of the nodes that has one connected to them, but that will leave me with some unwanted nodes as well, hence if I were to remove 6, 7, 8 ,9, 11, 13, 12 I'd still have an unwanted node of 10.
For those of you that do not understand what a feeder network is, it is basically a bunch of structures, manholes, handholes, cabinets, that carry the signal from the root structure 1 distributing it to areas through 2, 3, 4, and 5, till it reaches the customers. 6, 7, 8, 11, 13, 12, 9. as for 10, it is a sub manhole structure that simply is not part of the main network because it distributes within the branch. now I know what those are, but in the code. those are all nothing but a bunch of objects that contain what they are connected to. no types no nothing.
Following from the partial answer that you'd given, I think adding another property will give you the solution.
So far, you have 1,2,3,4,5 and 10.
The problem is 10, as we know, should not be part of the feeder network (since it's a branch).
If you look back, you can see that, for all nodes except 10, there's one path from node to source and one path from node to destination (the last node that you have have selected through your process from the queue) without any edge being visited twice.
Ex:
1.) 3->2->1 (source) & 3->4->5 (destination)
2.) 4->3->2->1 (source) & 4->5 (destination)
But in case of 10, one edge is going to be visited twice.
As in,
10->3->2->1 & 10->3->4->5
Here, as you can see, the edge 10-3 is visited twice which does not happen in case of other nodes.
Through this process, any node, which is not part of the feeder network, will be discarded.
From the information provided, this will give the right solution.
I would suggest you recursively search from your starting node. Descend through your nodes keeping track of the number of nodes you have passed though.
keep 2 arrays (or linked lists) one for your current path and one for your longest path. Add nodes to your current array as you descend and remove them as you return. do the same for the longest path array but only add to it as you exceed your current longest path. when you have searched the entire graph remove the last node in your array (since that will not be part of the main path).
There is probably a more efficient way to do this, which I'll have to give some thought to.
This code return the mainline for you:
static void Main()
{
Node node1 = new Node(1, null);
Node node6 = new Node(6, node1);
Node node2 = new Node(2, node1);
Node node7 = new Node(7, node2);
Node node8 = new Node(8, node2);
Node node3 = new Node(3, node2);
Node node10 = new Node(10, node3);
Node node8_ = new Node(8, node10);
Node node11 = new Node(11, node10);
Node node4 = new Node(4, node3);
Node node5 = new Node(5, node4);
Node node12 = new Node(12, node5);
Node node13 = new Node(13, node5);
List<List<Node>> MainLines = new List<List<Node>>();
foreach (var i in Node.HighestRankNodes)
{
List<Node> m = new List<Node>();
m.Add(i);
Node j = i.Parent;
while (j != null)
{
m.Insert(0, j);
j = j.Parent;
}
MainLines.Add(m);
}
foreach (var i in MainLines) Console.WriteLine("Mainline: " + string.Join(", ", i));
Console.ReadLine();
}
Node class:
public class Node
{
public int Number;
public Node Parent = null;
public int Rank = 0;
public static int currentMaxRank = 0;
public static List<Node> HighestRankNodes = new List<Node>();
public Node(int number, Node parent)
{
Number = number;
Parent = parent;
Rank = Parent != null ? Parent.Rank + 1 : 0;
if (currentMaxRank < Rank)
{
currentMaxRank = Rank;
HighestRankNodes.Clear();
}
if (currentMaxRank == Rank) HighestRankNodes.Add(this);
}
public override string ToString()
{
return Number.ToString();
}
}
Output:
Mainline: 1, 2, 3, 4, 5, 12
Mainline: 1, 2, 3, 4, 5, 13

Build BST from Preorder

Like many newbies, my head blows up from recursion. I looked up a lot of answers/explanations on SO. but I am still unclear on the concept. (This is not homework, I am trying to relearn what I unlearned and recursion was never a string point)
Given a preorder traversal, construct a binary tree. With recursion, it has to be deceptively simple :) but I just can't get it.
I see that the order of the arr has to be in the order nodes are inserted. What bugs me is:
What if the node already has a left/right? How does this work?
How can the recursion insert nodes, in say the following preorder?
12, 10, 6, 13
15 is root, 5, 3 and left
How does 6 get inserted correctly as 10's left child?
12
10 13
6*
Here is the skeleton code:
main()
{
int[] arr = {};
//make the first node a root node.
node n = new node(arr[0]);
buildbst(n, arr, 0)
}
buildbst(node root, int[] arr, int i)
{
if (i == arr.length) return;
if (arr[i] < root.data)
root.left = new node (arr[i]);
else
root.right = new node(arr[i]);
buildbst(root.left, arr, i++);
buildbst(root.right, arr, i++);
}
EDIT:
I just realised, if I pass in the recursive call buildbst(root.left, arr+i, i++)
is that the right way? Or am I approaching this all wrong - a mish-mash of dynamic programming and recursion and divide and conquer...
It can't already have a left / right child. You call it for the root, which has no children to start. Then you call it for the left child and create children where appropriate and call the function for those children and so on. You never visit the left child again once you go right and you can't get to a node from a function called on its child (since there is no connection up the tree, except the recursion stack).
This is what should happen when given 12, 10, 6, 13:
Creates the root 12
Calls buildbst(node(12), arr, 1)
Create node(12).left = node(10)
Calls buildbst(node(10), arr, 2)
Create node(10).left = node(6)
Calls buildbst(node(6), arr, 3)
13 > 12, must be right child of 12, so do nothing
13 > 12, must be right child of 12, so do nothing
Create node(12).right = node(13)
Calls buildbst(node(13), arr, 3)
Oh look, no more elements, we're done.
The above is not what will happen with your code for 2 reasons:
Your code will only create either a left or a right child, not both (because of the if-else))
Your code doesn't have the must be right child of '12' check, which is a little complex
The below code should cover it.
node buildbst(int[] arr)
{
node n = new node(arr[0]);
// 9999999999 is meant to be > than the biggest element in your data
buildbst(n, arr, 1, 9999999999);
return node;
}
int buildbst(node current, int[] arr, int i, int biggestSoFar)
{
if (i == arr.length) return i;
// recurse left
if (arr[i] < current.data)
{
current.left = new node(arr[i++]);
i = buildbst(current.left, arr, i, current.data);
}
// recurse right
if (i < arr.length && arr[i] < biggestSoFar)
{
current.right = new node(arr[i++]);
i = buildbst(current.right, arr, i, biggestSoFar);
}
return i;
}
Explanation:
The purpose of biggestSoFar is to prevent:
15 15
/ /\
5 versus (the correct) 5 20
/ \ /
1 20 1
When recursing left from 15 for example, we need to stop processing elements as soon as we get an element > 15, which will happen when we get 20. Thus we pass current.data and stop processing elements if we get a bigger value.
When recursing right from 5 for example, we need to stop processing elements as soon as we get an element > 15, which will happen when we get 20. Thus we pass biggestSoFar and stop processing elements if we get a bigger value.

How to find longest increasing sequence starting at each position within the array in O(n log n) time,

How could we find longest increasing sub-sequence starting at each position of the array in O(n log n) time, I have seen techniques to find longest increasing sequence ending at each position of the array but I am unable to find the other way round.
e.g.
for the sequence " 3 2 4 4 3 2 3 "
output must be " 2 2 1 1 1 2 1 "
I made a quick and dirty JavaScript implementation (note: it is O(n^2)):
function lis(a) {
var tmpArr = Array(),
result = Array(),
i = a.length;
while (i--) {
var theValue = a[i],
longestFound = tmpArr[theValue] || 1;
for (var j=theValue+1; j<tmpArr.length; j++) {
if (tmpArr[j] >= longestFound) {
longestFound = tmpArr[j]+1;
}
}
result[i] = tmpArr[theValue] = longestFound;
}
return result;
}
jsFiddle: http://jsfiddle.net/Bwj9s/1/
We run through the array right-to-left, keeping previous calculations in a separate temporary array for subsequent lookups.
The tmpArray contains the previously found subsequences beginning with any given value, so tmpArray[n] will represent the longest subsequence found (to the right of the current position) beginning with the value n.
The loop goes like this: For every index, we look up the value (and all higher values) in our tmpArray to see if we already found a subsequence which the value could be prepended to. If we find one, we simply add 1 to that length, update the tmpArray for the value, and move to the next index. If we don't find a working (higher) subsequence, we set the tmpArray for the value to 1 and move on.
In order to make it O(n log n) we observe that the tmpArray will always be a decreasing array -- it can and should use a binary search rather than a partial loop.
EDIT: I didn't read the post completely, sorry. I thought you needed the longest increasing sub-sequence for all sequence. Re-edited the code to make it work.
I think it is possible to do it in linear time, actually. Consider this code:
int a[10] = {4, 2, 6, 10, 5, 3, 7, 5, 4, 10};
int maxLength[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // array of zeros
int n = 10; // size of the array;
int b = 0;
while (b != n) {
int e = b;
while (++e < n && a[b] < a[e]) {} //while the sequence is increasing, ++e
while (b != e) { maxLength[b++] = e-b-1; }
}

how to rebuild BST using {pre,in,post}order traversals results

We know the pre-order, in-order and post-order traversals. What algorithm will reconstruct the BST?
Because it is BST, in-order can be sorted from pre-order or post-order <1>. Actually, either pre-order or post-order is needed only....
<1> if you know what the comparison function is
From pre-order and in-order, to construct a binary tree
BT createBT(int* preOrder, int* inOrder, int len)
{
int i;
BT tree;
if(len <= 0)
return NULL;
tree = new BTNode;
t->data = *preOrder;
for(i = 0; i < len; i++)
if(*(inOrder + i) == *preOrder)
break;
tree->left = createBT(preOrder + 1, inOrder, i);
tree->right = createBT(preOrder + i + 1, inOrder + i + 1, len - i - 1);
return tree;
}
The rationale behind this:
In pre-order, the first node is the root. Find the root in the in-order. Then the tree can be divided into left and right. Do it recursively.
Similar for post-order and in-order.
I personally found Dante's answer a little hard to follow. I worked my way through the solution and found it to be similar to the one posted here http://geeksforgeeks.org/?p=6633
Complexity is O(N^2).
Here's another approach for building a tree using post-order traversal: http://www.technicallyidle.com/2011/02/15/build-binary-search-tree-using-post-order-traversal-trace/
Hope this helps
For reconstruction of a binary tree either preorder+inorder or postorder+inorder is needed. As already pointed out for a BST we can reconstruct using either preorder or postorder as sorting either of them will give us the inorder.
You can use the following function which is modification of the code given by #brainydexter to reconstruct the tree without using the static variable:
struct node* buildTree(char in[],char pre[], int inStrt, int inEnd,int preIndex){
// start index > end index..base condition return NULL.
if(inStrt > inEnd)
return NULL;
// build the current node with the data at pre[preIndex].
struct node *tNode = newNode(pre[preIndex]);
// if all nodes are constructed return.
if(inStrt == inEnd)
return tNode;
// Else find the index of this node in Inorder traversal
int inIndex = search(in, inStrt, inEnd, tNode->data);
// Using index in Inorder traversal, construct left and right subtress
tNode->left = buildTree(in, pre, inStrt, inIndex-1,preIndex+1);
tNode->right = buildTree(in, pre, inIndex+1, inEnd,preIndex+inIndex+1);
return tNode;
}
Here is a Ruby recursive solution
def rebuild(preorder, inorder)
root = preorder.first
root_inorder = inorder.index root
return root unless root_inorder
root.left = rebuild(preorder[1, root_inorder], inorder[0...root_inorder])
root.right = rebuild(preorder[root_inorder+1..-1], inorder[root_inorder+1..-1])
root
end
And an example
class Node
attr_reader :val
attr_accessor :left, :right
def initialize(val)
#val = val
end
def ==(node)
node.val == val
end
def inspect
"val: #{val}, left: #{left && left.val || "-"}, right: #{right && right.val || "-"}"
end
end
inorder = [4, 7, 2, 5, 1, 3, 8, 6, 9].map{|v| Node.new v }
preorder = [1, 2, 4, 7, 5, 3, 6, 8, 9].map{|v| Node.new v }
tree = rebuild(preorder, inorder)
tree
# val: 1, left: 2, right: 3
tree.left
# val: 2, left: 4, right: 5
tree.left.left
# val: 4, left: -, right: 7

Resources