I know the recursive code could be written for finding the minimum height. But for a very large tree (like million nodes in leftside vs 1 node in right side) - the approach isn't good. So please let me know if following code is fine, it uses BFS:-
if (root == null)
{
return 0;
}
Queue<Node> queue = new Queue<Node>();
queue.Enqueue(root);
int min = 0;
while (queue.Count > 0)
{
Node temp = queue.Dequeue();
if (temp.LeftChild == null)
{
return ++min;
}
if (temp.LeftChild != null)
{
++min;
queue.Enqueue(temp.LeftChild);
}
if (temp.RightChild == null)
{
return ++min;
}
if (temp.RightChild != null)
{
++min;
queue.Enqueue(temp.RightChild);
}
}
return 0;
So for a tree like
1
/ \
2 3
/
4
/
6
The above returns 1, (as per Floor(Log(n))?
Thanks.
The idea is perfect. But the code still can be bettered a bit.
Why do you increase min every time you dequeue item? And you do it twice, it is two times worse :) If you supose this variable to be nodes counter then it is incorrect too because you did not count root element. And hence it must be called in the other way, not min.
Why do you check if children are null twice? If statements spoil the pipe, their count must be minimized.
The idea is next. Let`s call the row of the nodes of the equal level full if every node in it has both children. Then min height is the count of full rows in the tree. It equals closest power index of 2 to the items count in all the full rows + 1.
A code:
if (root == null)
{
return 0;
}
Queue<Node> queue = new Queue<Node>();
queue.Enqueue(root);
int nodesCount = 0;
while (queue.Count > 0)
{
Node temp = queue.Dequeue();
if (temp.LeftChild == null || temp.RightChild == null)
{
return Floor(Log(nodesCount + 1)/Log(2)); // It can be made much better using, for example, bitwise operations but this is not the question`s topic
}
++nodesCount;
queue.Enqueue(temp.LeftChild);
queue.Enqueue(temp.RightChild);
}
return Infinity; // :)
Use 2 stacks to do a "Zig-zag" traversal. Count the number of times where you need to flip the "leftToRight" flag.
Related
Can I implement a binary heap by only using a TreeNode inferface (has children, or left/right, or/and parent.. something like this)?
I want to not rely on using array or linked list.
If I don't use array or linked list, I have a trouble inserting the next element in the correct place & keep it a complete binary tree (all non-leaf nodes are full). Also have trouble taking out the root and re-heapifying.
One key observation is this:
The path from the root to the last leaf in a complete binary tree is represented by the binary representation of the size of the tree (number of nodes in the tree).
For instance, this tree has 9 nodes.
1
/ \
4 2
/ \ / \
6 5 3 7
/ \
9 8
9 in binary is 1001. Skipping the most significant "1", this can be read from left-to-right as 0, 0, 1 or "left-left-right". That describes indeed the path from root to the leaf node with value 8!
The same principle holds for when you need to find the insertion point for a new node. Then first increase the size, so this becomes 10 in the example. The binary representation is 1010. Skipping the first digit, this represents "left-right-left". The last direction ("left") gives information about the edge that must be added. And indeed, "left-right" leads us to the node with value 5, and a new node has to be inserted as left-child of that node!
To restore the heap property after an insertion, keep track of the path towards the newly inserted leaf (for example, when coming back out of a recursive function), and wind that path back, each time verifying the heap property, and swapping values when necessary.
Similarly, for an extraction of the root value: first find the node to delete (see above), delete that node and assign the deleted value to the root node. Then sift down the heap to restore the heap property.
Here is an implementation in plain JavaScript -- it should be easy to port this to any other language:
class Node {
constructor(value) {
this.value = value;
this.left = this.right = null;
}
swapValueWith(other) { // We don't swap nodes, just their values
let temp = this.value;
this.value = other.value;
other.value = temp;
}
}
class HeapTree {
constructor() {
this.root = null;
this.size = 0;
}
insert(value) {
this.size++;
if (this.root == null) {
this.root = new Node(value);
} else { // Use the binary representation of the size to find insertion point
this.insertRecursive(this.root, 1 << (Math.floor(Math.log2(this.size)) - 1), value);
}
}
insertRecursive(node, bit, value) {
let side = this.size & bit;
let child;
if (side > 0) {
if (bit == 1) node.right = new Node(value);
child = node.right;
} else {
if (bit == 1) node.left = new Node(value);
child = node.left;
}
if (bit > 1) this.insertRecursive(child, bit>>1, value)
if (node.value > child.value) node.swapValueWith(child); // sift up
}
extract() {
if (this.root == null) return; // Nothing to extract
let value = this.root.value; // The value to return
if (this.size == 1) {
this.root = null;
} else {
// Use the binary representation of the size to find last leaf -- to be deleted
this.root.value = this.deleteRecursive(this.root, 1 << (Math.floor(Math.log2(this.size)) - 1));
// Sift down
let node = this.root;
while (true) {
let minNode = node;
if (node.left != null && node.left.value < minNode.value) minNode = node.left;
if (node.right != null && node.right.value < minNode.value) minNode = node.right;
if (minNode === node) break;
node.swapValueWith(minNode);
node = minNode;
}
}
this.size--;
return value;
}
deleteRecursive(node, bit) {
let side = this.size & bit;
let child;
if (side > 0) {
child = node.right;
if (bit == 1) node.right = null;
} else {
child = node.left;
if (bit == 1) node.left = null;
}
return bit == 1 ? child.value : this.deleteRecursive(child, bit>>1);
}
}
// Demo
let heap = new HeapTree();
for (let value of [4,2,5,8,7,9,0,3,1,6]){
heap.insert(value);
}
// Output the values in sorted order:
while (heap.root != null) {
console.log(heap.extract());
}
I am looking at this challenge:
Suppose two subtrees in a binary search tree have been swapped, and that the BST property is broken. Devise an algorithm that identifies the two swapped subtrees in O(n) time.
My Thoughts
When an inorder traversal of a BST is done, the elements are sorted.
Now when two subtrees are swapped, the inorder traversal will
not be sorted. So if you compare the inorder traversal of the original
tree and the swapped one, it would be like you have taken two subsets
of a sorted array in the original one and swapped them.
But now the challenge comes to identify the corresponding subtrees, and I have no idea how to derive that from the inorder traversal.
First of all, if the tree has duplicate values and they are not always stored at the same side of their parent (that has the same value) then it is not always possible to detect a swap. Imagine a tree with the same value in many different places:
______ 8 _____
/ \
_ 8_ ___ 8 __
/ \ / \
2 8* 8* 14
/ \ / \ / \ / \
1 3 8 8 8 8 13 15
This is a valid BST. And if we were to swap the two subtrees marked with an asterisk, we would end up with a valid BST, and so there is no way to detect which subtrees were swapped. It could well have been the children of the first *-node that had been swapped, or the children of the second *-node that had been swapped. There is no way to know this.
So, it is only possible to detect a swap, if the result of the swap inserts the two involved subtrees at invalid positions. One way to ensure this, is to dictate that duplicate values should always be stored at the same side (for example at the right) of the parent node that has the same value.
Algorithm
An in-order traversal is a good idea, but the idea to then verify that the visited nodes come out in their right order is less useful.
Instead, during the traversal, keep track of the "window" (a min-max range) between which values are allowed in the currently visited subtree. As soon as you find a child that has a value outside that window, report that child node as being misplaced, and don't continue in that child's subtree (as we may assume that the subtree itself is a consistent BST).
If there was indeed a single swap, you will find two such anomalies.
Code
Here is some code (actually JavaScript), assuming you have a Node class with the usual value, left and right properties, and duplicate values can only be stored at the right of a parent node having the same value. The function takes as argument the root node of the BST:
function findSwap(root) {
let results = []; // This array (stack) will be filled with 2 nodes
// Recursive function, which will populate the array:
function recur(node, min, max) {
if (node.value < min || node.value >= max) { // Out of range!
results.push(node); // log this node, and don't bother recurring deeper
} else {
if (node.left != null) {
recur(node.left, min, node.value); // Narrow the window
}
if (node.right != null) {
recur(node.right, node.value, max); // Narrow the window
}
}
}
// Start the search with an infinite window
recur(root, -Infinity, Infinity);
return results; // Return the two nodes found as an array of nodes
}
Note that the out-of-range condition needs exactly those inequalities:
node.value < min || node.value >= max
The min value represents an allowable value, but the max does not. So the valid value range of a node is [min, max) (including min, excluding max). This follows from the extra requirement that duplicate values should always be stored at the right side. If you would decide to always store them on the left side, then the equality should be allowed on the min value and not the max value.
Implementation
Below is a runnable snippet which first creates this binary search tree:
______ 8 _____
/ \
_ 4_ __ 12 __
/ \ / \
2 6 10 14
/ \ / \ / \ / \
1 3 5 7 9 11 13 15
It then swaps the subtree at 6 with the subtree at 10. And finally it calls the above function and reports the result:
function findSwap(root) {
let results = [];
function recur(node, min, max) {
if (node.value < min || node.value >= max) {
results.push(node);
} else {
if (node.left) {
recur(node.left, min, node.value);
}
if (node.right) {
recur(node.right, node.value, max);
}
}
}
recur(root, -Infinity, Infinity);
return results;
}
// Define the Node class
class Node {
constructor(value) {
this.value = value;
this.left = this.right = null;
}
add(...values) { // Allow adding more than one value with one call
for (let value of values) {
if (value < this.value) {
if (this.left) this.left.add(value);
else this.left = new Node(value);
} else {
if (this.right) this.right.add(value);
else this.right = new Node(value);
}
}
}
}
// Demo:
// Create a complete binary tree with values 1 through 15
let root = new Node(8); // root
root.add( 4, 12, // level 1
2, 6, 10, 14, // level 2
1, 3, 5, 7, 9, 11, 13, 15); // level 3
// Perform a swap of the subtree rooted in 6 and in 10:
[root.left.right, root.right.left] = [root.right.left, root.left.right];
// Call the function:
let result = findSwap(root);
// Report which subtrees were swapped
console.log(result[0].value, result[1].value); // 10, 6
Of course, if the tree did not have a swap of exactly two distinct subtrees, then the returned array will not always give reliable information, since it assumes that a wrongly attached subtree is itself still consistent.
But if the returned array is empty, you may conclude that the BST is fine.
Detecting move of one subtree
In comments you gave an example of a subtree that was moved (not swapped with another):
In that case the above code will return just the misplaced subtree, but it will not give information about where this subtree came from.
If also this case should be covered, then we need to change the output, because it doesn't really help to list the other (degenerate) "subtree" as null. So then I propose to have the output state which is the parent and the side of the edge where the subtree was cut away.
The above algorithm could be adapted so that it will do some post processing in case there is only one anomaly found: in that case a simple binary search will find the insertion spot for that misplaced subtree. This post processing represents O(logn) time complexity, so it does not impact the overall linear time complexity.
Here is the adapted code, together with the example you had posted:
function findSwap(root) {
let results = [];
function recur(node, parent, side, min, max) {
if (node.value < min || node.value >= max) {
results.push({parent, side, node});
return;
}
if (node.left != null) {
recur(node.left, node, "left", min, node.value);
}
if (node.right != null) {
recur(node.right, node, "right", node.value, max);
}
}
recur(root, null, "root", -Infinity, Infinity);
// Post processing:
if (results.length === 1) {
// It was not a swap, but a move
let value = results[0].node.value;
// Look up the insertion point for the misplaced value (and its subtree)
let parent = root;
while (results.length < 2) {
if (value < parent.value) {
if (parent.left == null) {
result.push({parent, side: "left", node: null });
} else {
parent = parent.left;
}
} else {
if (parent.right == null) {
results.push({parent, side: "right", node: null });
} else {
parent = parent.right;
}
}
}
}
return results;
}
// Define the Node class
class Node {
constructor(value) {
this.value = value;
this.left = this.right = null;
}
add(...values) { // Allow adding more than one value with one call
for (let value of values) {
if (value < this.value) {
if (this.left) this.left.add(value);
else this.left = new Node(value);
} else {
if (this.right) this.right.add(value);
else this.right = new Node(value);
}
}
}
}
// Demo (as in image):
let root = new Node(5); // root
root.add( 3, 8, // level 1
2, 4, 7, 9); // level 2
// Perform the move of the subtree rooted in 8, below the node 4
root.left.right.right = root.right;
root.right = null;
// Call the function:
let result = findSwap(root);
// Report which subtrees were swapped
function edgeName(edge) {
return "the " + edge.side + " child (" + (edge.node?.value??null) + ") of node " + edge.parent.value;
}
console.log(edgeName(result[0]) + " was swapped with " + edgeName(result[1]));
Hi can someone help me out which sorting algorithm used in this function
public void sortList() {
Node current = null, index = null;
int temp;
//Check whether list is empty
if(head == null) {
return;
}
else {
//Current will point to head
for(current = head; current.next != null; current = current.next) {
//Index will point to node next to current
for(index = current.next; index != null; index = index.next) {
//If current's data is greater than index's data, swap the data of current and index
if(current.data > index.data) {
temp = current.data;
current.data = index.data;
index.data = temp;
}
}
}
}
}
By the way it is Doubly Link List
The current node is fixed and then iteration is done from next node to the end(via index variable), at the end of one iteration of outer loop the node pointed to by current has correct value, then the current is progressed to next node.
This is Selection Sort, the most elementary sort
Fun fact : although slow because of complexity O(n^2) selection sort can be used when the write operation is expensive because it only swaps max n times for a list of size n
I have a linked list which is cyclic and I want to find out the total number of elements in this list. How to achieve this?
One solution that I can think of is maintaining two pointers. First pointer (*start) will always point to the starting node, say Node A.
The other pointer (*current) will be initialized as: current = start->next.
Now, just iterate each node with current -> next until it points to start.
And keep incrementing a counter: numberOfNodes++;
The code will look like:
public int countNumberOfItems(Node* start){
Node* current = start -> next;
int numberOfNodes = 1; //Atleast the starting node is there.
while(current->next != start){
numberOfNodes++;
current = current->next;
}
return numberOfNodes;
}
Let's say the list has x nodes before the loop and y nodes in the loop. Run the Floyd cycle detection counting the number of slow steps, s. Once you detect a meet point, run around the loop once more to get y.
Now, starting from the list head, make s - y steps, getting to the node N. Finally, run two slow pointers from N and M until they meet, for t steps. Convince yourself (or better prove) that they meet where the initial part of the list enters the loop.
Therefore, the initial part has s - y + t + 1 nodes, and the loop is formed by y nodes, giving s + t + 1 total.
You just want to count the nodes in your linked list right? I've put an example below. But in your case there is a cycle so you also need to detect that in order not to count some of the nodes multiple times.
I've corrected my answer there is now an ordinary count and count in loop (with a fast and slow pointer).
static int count( Node n)
{
int res = 1;
Node temp = n;
while (temp.next != n)
{
res++;
temp = temp.next;
}
return res;
}
static int countInLoop( Node list)
{
Node s_pointer = list, f_pointer = list;
while (s_pointer !=null && f_pointer!=null && f_pointer.next!=null)
{
s_pointer = s_pointer.next;
f_pointer = f_pointer.next.next;
if (s_pointer == f_pointer)
return count(s_pointer);
}
return 0;
}
First find the cycle using Floyd Cycle Detection algorithm and also maintain count when you checking cycle once found loop then print count for the same.
function LinkedList() {
let length = 0;
let head = null;
let Node = function(element) {
this.element = element;
this.next = null;
}
this.head = function() {
return head;
};
this.add = function(element) {
let node = new Node(element);
if(head === null){
head = node;
} else {
let currentNode = head;
while(currentNode.next) {
currentNode = currentNode.next;
}
currentNode.next = node;
}
};
this.detectLoopWithCount = function() {
head.next.next.next.next.next.next.next.next = head; // make cycle
let fastPtr = head;
let slowPtr = head;
let count = 0;
while(slowPtr && fastPtr && fastPtr.next) {
count++;
slowPtr = slowPtr.next;
fastPtr = fastPtr.next.next;
if (slowPtr == fastPtr) {
console.log("\n Bingo :-) Cycle found ..!! \n ");
console.log('Total no. of elements = ', count);
return;
}
}
}
}
let mylist = new LinkedList();
mylist.add('list1');
mylist.add('list2');
mylist.add('list3');
mylist.add('list4');
mylist.add('list5');
mylist.add('list6');
mylist.add('list7');
mylist.add('list8');
mylist.detectLoopWithCount();
There is a "slow" pointer which moves one node at a time. There is a "fast" pointer which moves twice as fast, two nodes at a time.
A visualization as slow and fast pointers move through linked list with 10 nodes:
1: |sf--------|
2: |-s-f------|
3: |--s--f----|
4: |---s---f--|
5: |----s----f|
At this point one of two things are true: 1) the linked list does not loop (checked with fast != null && fast.next != null) or 2) it does loop. Let's continue visualization assuming it does loop:
6: |-f----s---|
7: |---f---s--|
8: |-----f--s-|
9: |-------f-s|
10: s == f
If the linked list is not looped, the fast pointer finishes the race at O(n/2) time; we can remove the constant and call it O(n). If the linked list does loop, the slow pointer moves through the whole linked list and eventually equals the faster pointer at O(n) time.
I'm trying this question for sometime but couldn't figure out the algorithm. My preference is to do it iteratively. Till now, I've figure out something but not sure on some point.
Currently, My algorithm looks like:
First traverse the tree to find the node
While traversing the tree, keep track of the previous node.
if you find the node, check if left child is present then that is successor return.
if left child is not present then check if right child is present the that is successor and return.
if the node(is left to the parent) and don't have left or right child then we've saved the prev node earlier then either prev or prev's right child is the successor.
But what if the node we found is in the right to parent and don't have left or right child how to find successor of this node?
May be there are many flaws in this algorithm as still I've not understand all the cases properly. If anyone has any idea or algorithm please share.
Thanks in advance.
when you find a node in preorder, to find its successor is just travesing to its next node.
what I was thinking first is the relationship of a node and its successor's values in pre-oder, but I found that it seems not very clear like the relationship in in-order. I think there is only one step beteen a node and its successor(if exists) : just move on travesing. So I design this algorithm.
my algorithm below is based on preorder travesal, it can run on a binary tree,not only BST.
#define NOT_FOUND -1
#define NEXT 0
#define FOUND 1
struct node {
struct node *p;//parent,but useless here
struct node *l;//left child
struct node *r;//right child
int value;
};
int travese(struct node* bnode, int* flag,int value)
{
if(bnode == NULL)
return 0;
else
{
if(*flag == FOUND)
//when the successor is found,do pruning.
return 1;
else if(*flag == NEXT) {
printf("successor:%d\n",bnode->value);
*flag = FOUND;
return 1;
}
else if(*flag == NOT_FOUND && bnode->value == value)
*flag = NEXT;
travese(bnode->l,flag,value);
travese(bnode->r,flag,value);
}
return 0;
}
and use it by:
int flag = NOT_FOUND;
travese(root,&flag,value);
if(flag == NEXT || flag == NOT_FOUND)
printf("no successor.\n");
EDIT:
turning a recurrence algorithm to a iterative one is not difficult by using a stack like below:
int preorder_travese_with_stack(struct node* bnode, int* flag,int value)
{
if(bnode == NULL)
return 0;
struct stack s;//some kind of implement
push(s,bnode);
while(NotEmpty(s) && *flag) {
struct node *curNode = pop(s);
if(*flag == NEXT) {
printf("successor:%d\n",curNode->value);
*flag = FOUND;
return 1;
}
else if(*flag == NOT_FOUND && curNode->value == value)
*flag = NEXT;
push(s,curNode->r);
push(s,curNode->l);
}
return 0;
}
but according to your comment and original description, I think the one you want is iterative algorithm without a stack.here it is.
After thinking ,searching and trying, I wrote one. When travse the tree iteratively without stack , the parent of a node is not useless any more. In a path, some nodes is visited not only once, and you need to record its direction at that time.
int preorder_travese_without_stack(struct node *root,int value,int *flag)
{
int state=1;
//state: traveral direction on a node
//1 for going down
//2 for going up from its left chlid
//3 for going up from its right child
struct node *cur = root;
while(1) {
if(state == 1) //first visit
{
//common travese:
//printf("%d ",cur->value);
if(cur->value == value && *flag == NOT_FOUND)
*flag = NEXT;
else if (*flag==NEXT) {
*flag = FOUND;
printf("successor:%d\n",cur->value);
break;
}
}
if((state == 1)&&(cur->l!=NULL))
cur = cur->l;
else if((state==1)&&(cur->l==NULL))
{
state = 2;
continue;
}
else if(state==2) {
if(cur->r != NULL ) {
cur=cur->r;
state = 1;
}
else
{
if(cur->p!=NULL)
{
if(cur==cur->p->r)
state = 3;
//else state keeps 2
cur=cur->p;
}
else //cur->p==NULL
{
if(cur->p->r!=NULL)
{
cur=cur->p->r;
state = 1;
}
else
break;
//end up in lchild of root
//because root's rchild is NULL
}
}
continue;
}
else //state ==3
{
if(cur->p!=NULL)
{
if(cur==cur->p->l)
state = 2;
else
state = 3;
cur=cur->p;
continue;
}
else
break;
}
}
}
the usage is the same as the first recurrence one.
If you are confused yet,mostly about the direction of a node , you can draw a tree and draw the path of pre-order traverse on paper,it would help.
I'm not sure there are bugs left in the code,but it works well on the tree below:
0
/ \
1 2
/ \ / \
3 4 5 6
btw,"wirte down pre-order (or else) travese algorithm of a tree both by recurrence and iteration" is a common interview problem, although solving the latter by a stack is permitted.but I think the BST requirement is unnecessary in pre-order travese.
My implementation of the algorithm does not use the key. Therefore it is possible to use it in any kind of binary tree, not only in Binary search trees.
The algorith I used is this:
if given node is not present, return NULL
if node has left child, return left child
if node has right child, return right child
return right child of the closest ancestor whose right child is present and not yet processed
Bellow there is my solution.
TreeNode<ItemType>* CBinaryTree<ItemType>::succesorPreOrder(TreeNode<ItemType> *wStartNode)
{
//if given node is not present, return NULL
if (wStartNode == NULL) return NULL;
/* if node has left child, return left child */
if (wStartNode->left != NULL) return wStartNode->left;
/* if node has right child, return right child */
if (wStartNode->right != NULL) return wStartNode->right;
/* if node isLeaf
return right child of the closest ancestor whose right child is present and not yet processed*/
if (isLeaf(wStartNode)) {
TreeNode<ItemType> *cur = wStartNode;
TreeNode<ItemType> *y = wStartNode->parent;
while (y->right == NULL && y->parent!=NULL){
cur = y;
y = y->parent;
}
while (y != NULL && cur == y->right) {
cur = y;
y = y->parent;
}
return y->right;
}
}
bool CBinaryTree<ItemType>::isLeaf(TreeNode<ItemType> *wStartNode){
if (wStartNode->left == NULL && wStartNode->right == NULL) return true;
else return false;
};