I'm new to the concept of graphs and trees.Below is the inorder tree traversal of tree.
if(n!=null){
treeTraversal(n.left);
System.out.println(n.val);
treeTraversal(n.right);
}
I'm not able to understand the flow as it involves recursion. Can somebody explain me how does control flow takes place with respect to stack.
Let's say I have a tree which is something like:
4
/ \
2 5
/ \
1 3
Your code will first put the recurse through the left children 4 -> 2 -> 1. Since 1 does not have a left child (it is null), it will print 1 and then pop the stack. Next up in the recursion is 2. It will print 2 then traverse the right child of 2 i.e 3. It will print 3, then pop the stack. Then it will print 4, then 4's right child 5. The sequence of prints will be 1, 2, 3, 4, 5. Here is a good animation too.
The image shows the execution of the code with a simple tree, it should help you to understand how recursion works, just follow the arrows.
Under each stack there is the tree diagram that shows in yellow the current node (click the image to expand it):
This is an inOrder traversal you first visit left child if exist if not you print the nod and the you travers to left node
for example in this tree your code out put will be
10, 4, 11, 2, 5, 9, 1, 7, 6, 8, 3
We have preOrder and postOrde traversal as well
preOrder
preorder(Node N)
if (N != null)
Visit N;
for each child Y of N
preorder(Y);
and post order
postorder(Node N)
if (N != null)
for each child Y of N
postorder(Y);
Visit N;
Related
We have a given array and we want to print each node's level in the BST.
For example if the given array is: {15, 6, 2, 10, 9, 7, 13}
then the answer is:
1 2 3 3 4 5 4
(it means that the level of node that stores 15 is 1 and ...)
I have some algorithms in my mind but I don't know how to implement them in code.
These are the steps that you should follow :
Create a binary search tree from the elements given in the array.
Write a function findLevel( Node root, int value) to find the level of any value passed to this function.
Iterate the array and pass each array element as an argument to findLevel( Node root, int value) and print the values returned from the function.
I am working on below interview question:
Given a singly linked list where elements are sorted in ascending
order, convert it to a height balanced BST.
For this problem, a height-balanced binary tree is defined as a binary
tree in which the depth of the two subtrees of every node never differ
by more than 1.
I am trying to understand below solution and its complexity? Can someone help me understand how it works? Is below solution O(n) time complexity and O(log n) space complexity?
Also is below algorithm better than "counting the number of nodes in the given Linked List. Let that be n. After counting nodes, we take left n/2 nodes and recursively construct the left subtree. After left subtree is constructed, we allocate memory for root and link the left subtree with root. Finally, we recursively construct the right subtree and link it with root. While constructing the BST, we also keep moving the list head pointer to next so that we have the appropriate pointer in each recursive call"
public TreeNode toBST(ListNode head) {
if(head==null) return null;
return helper(head,null);
}
public TreeNode helper(ListNode head, ListNode tail){
ListNode slow = head;
ListNode fast = head;
if(head==tail) return null;
while(fast!=tail && fast.next!=tail){
fast = fast.next.next;
slow = slow.next;
}
TreeNode thead = new TreeNode(slow.val);
thead.left = helper(head,slow);
thead.right = helper(slow.next,tail);
return thead;
}
BST-construction
A balanced tree can be constructed from a sorted list by subdividing the list into two equally long lists with one element in the middle being used as a root. E.g.:
1. [1, 2, 3, 4, 5, 6, 7]
2. 4
/ \
[1, 2, 3] [5, 6, 7]
3. 4
/ \
2 6
/ \ / \
1 3 5 7
Even if the two sublists differ by one element, they can at most differ by 1 in their height, thus making the tree balanced. By taking the middle element of the list the resulting tree is guaranteed to be a BST, since all smaller elements are part of the left subtree and all larger elements of the right subtree.
slow and fast
Your code works using two iterators, where one (fast) iterates over nodes twice as fast as the other (slow). So when fast has reached either the tail or the node right before the tail of the list, slow must be at the node in the middle of the list, thus dividing the list into two sublists of same length (up to at most one element difference), which can then be recursively processed as shown in the above diagramm.
Runtime Complexity
The algorithm runs in O(n lg n). Let's start with the recurrence of helper:
T(n) = n / 2 + 2 * T(n / 2)
T(1) = 1
In each call of helper, we must find the middle-node of the linkedlist defined by the two parameters passed to helper. This can only be done in n / 2 steps, since we can only walk linearly through the list. In addition, the helper is called recursively twice on linkedlists of half the size of the original list to build the left and right subtree.
Applying the Master-theorem(case 2) to the above recurrence, we get O(n lg n).
Space complexity
Space-complexity also needs to take the produced output-structure into account. Since each element of the input-linked list is converted into a node in the BST, the complexity is O(n).
EDIT
If the output is ignored, the space-complexity is solely dependent on the recursion-depth, which in turn is O(lg n), thus making the space-complexity O(lg n).
I am trying to learn graphs as well using Dijkstra’s path and am using this geeks for geeks tutorial. I think i understand how it works using weight to find the shortest path. However this may be dumb but i dont understand how to find the destination point by looking at the code. or how the 9 inputs are
Why are there 9 inputs cant it work with only three? And how does the program know where to end?
So, to address the first half of your question, there isn't a predetermined "destination node" with Dijsktra's algorithm, moreso just a final result.
In this example from the GeeksforGeeks code,
void dijkstra(int graph[V][V], int src)
We can see that the algorithm wants an array of all of the nodes, and which node you'll be starting from. Each node in this array has 9 inputs which correspond to that node's given distance from any other node, where a value of 0 represents no connection. For example, the "0" node has values:
{0, 4, 0, 0, 0, 0, 0, 8, 0}
Which mean that node 0 is 4 units away from node 1, 8 units away from node 7, and either has no connection to, or IS one of the other 7 nodes. If you only have 3 nodes, then you'd use 3 inputs to represent the possible distances between all 3.
When the program has exhausted all possible nodes and paths, the algorithm will stop. This algorithm looks for a minimum spanning tree, not a path from point A to point B.
The program in that example ends when all nodes have been visited, it does not choose a specific destination. It calculates the minimum distance (and path) from node 0 to every node in the graph.
There are 9 nodes in the example, but ofcourse you can also use 3 nodes, or 1000 nodes..
I have an algorithm that checks whether or not a game row can be solved. The game row is an array of positive integers, where the last element is 0. The game marker starts at index 0 and moves along the array the number of steps indicated by the integer it is positioned at.
For example, [1, 1, 0] returns true, while [1, 2, 0] returns false.
The marker can also move left or right in order to solve the game.
That is, [3, 3, 2, 2, 0] is solvable.
Algorithm recursiveSolvable(gameArray, index)
if index = gameArray.length - 1 // the last element has been reached
return true
if index < 0 || index >= gameArray.length || arrayList.contains(index)
return false
arrayList.add(index) // store visited indices to avoid infinite loop
else
// move towards the goal (last element) if possible
// otherwise, trace back steps to find another way
return recursiveSolvable(gameArray, index + gameArray[index])
|| recursiveSolvable(gameArray, index - gameArray[index])
I have tried with a few examples of game rows and calculated the time complexity in the worst case:
[2, 0] has 2 recursive calls where the first one returns false, and the second one as well
[1, 1, 2, 0] has 5:
go right || go left - false
|
go right || go left - false
|
go right || go left - false (because index 0 has been visited)
|
false (then go left)
Other cases gave me numbers that I couldn't find the relation with the input size, but when I run the program with input size n = 100, the output is shown instantly, so I assume the time complexity is not O(2^n) (like binary recursion). I am more leaning towards O(n)...
As for the space complexity, I have no idea how to find it.
The run time is indeed more like O(n). This is because each index position is investigated only once (due to the test with the arrayList).
The exact bound depends also on the data structure used for arrayList. Is it really a List or a HashSet?
The space complexity is O(n) for the same reason. There can only be one incarnation of the recursive method for each index position.
ok i am given a bunch of leafs 10,9,7,8 and i need to create a sum tree from them as such
i need to find the sum of what is circled.
the problem is really a weight problem where i can choose two elements at a time to add them and their combined weight is the work done to combine the elements and i have to keep doing this till all the weights are combined while doing the minimum amount of work but i have turned it into this because i think this is the way to solve it.
is this the best way to solve this problem or is there a better way?
what would be the fastest way to create this tree and calculate the sum of those nodes?
The greedy solution:
Put all leaves in a priority queue (minimum weight comes out first).
While the queue contains more than one tree, pull out the two least-weight trees, join them and insert the joint tree into the queue.
When the queue contains only a single tree, that is your solution.
The greedy solution works:
Given any binary tree built from the leaves, each leaf contributes depth*weight to the total work/cost. (Where the depth of a leaf is the length of the path from the root to the leaf, e.g. in
18
/ \
3 15
/ \ / \
1 2 4 11
/ \
5 6
the leaves 1, 2, and 4 have depth 2, the leaves 5 and 6 have depth 3.)
So for any given shape of the tree, the smallest total cost is obtained when the lightest leaves are the deepest. Therefore a minimum cost tree is reached when the first step is joining the two lightest leaves to a new tree.
When some leaves have already been joined, the total cost of building the tree is (cost so far) + (cost of building cheapest tree considering the non-singleton trees as leaves).
So in the minimum cost tree, by the reasoning above, the two lightest "leaves" must be at the deepest level, hence can be joined to form a new subtree.
Use a stack machine. Push the leaves until the stack has 2 elements. Pop those elements, add (sub, mult, div, etc.) them, and push the result. Continuously do that until the input has no more elements. The final result is on top of the stack. This algorithm does arithmetic in the same order the sum tree would do it.
code stack
--------------------------
push 10 10$
push 9 9, 10$
pop a 10$
pop b $
push a+b 19$
push 7 7, 19$
push 8 8, 7, 19$
pop a 7, 19$
pop b 19$
push a+b 15, 19$
pop a 19$
pop b $
push a+b 34$
done 34$
Here is the implementation using Java
public static int sumTree(BinaryTreeNode<Integer> node) {
if (node == null) {
return 0;
}
int oldVal = node.getData();
node.setData(sumTree(node.getLeft()) + sumTree(node.getRight()));
return oldVal + node.getData();
}
Here is the test case
#Test
public void sumTreeTest() {
BinaryTreeNode<Integer> bt = BinaryTreeUtil.<Integer>fromInAndPostOrder(new Integer[]{8,-2,-4,10,7,6,5}, new Integer[]{8,-4,-2,7,5,6,10});
BinaryTreeUtil.sumTree(bt);
List<Integer> result = new ArrayList<Integer>();
BinaryTreeUtil.printInOrder(bt, result);
assertThat(result.toArray(new Integer[0]), equalTo(new Integer[]{0, 4, 0, 20, 0, 12, 0}));
//System.out.println(Arrays.toString(result.toArray()));
}