Find Ancestor method for binary search tree is not working - data-structures

I had written the method for finding a node's parent in C# (c-sharp) but my code is not working correctly. Exceptions: System.NullReferenceException is thrown when I try to delete a node who's parent is null.
public TreeNode FindParent(int value, ref TreeNode parent)
{
TreeNode currentNode = root;
if (currentNode == null)
{
return null;
}
while (currentNode.value != value)
{
if (value < currentNode.value)
{
parent = currentNode;
currentNode = currentNode.leftChild;
}
if (value > currentNode.value)
{
parent = currentNode;
currentNode = currentNode.rightChild;
}
}
return currentNode;
}
public void Delete(int value)
{
TreeNode parent = null;
TreeNode nodeToDelete = FindParent(value, ref parent);
if (nodeToDelete == null)
{
throw new Exception("Unable to delete node: " + value.ToString());
}
//CASE 1: Nod has 0 children.
if (nodeToDelete.leftChild == null && nodeToDelete.rightChild == null)
{
if (parent.leftChild == nodeToDelete)
{
parent.leftChild = null;
}
if (parent.rightChild == nodeToDelete)
{
parent.rightChild = null;
}
count--;
return;
}
//CASE 2: Nod has 1 left || 1 right barn
if (nodeToDelete.leftChild == null && nodeToDelete.rightChild != null)
{
nodeToDelete.rightChild = parent.rightChild;
nodeToDelete = null;
count--;
return;
}
if (nodeToDelete.leftChild != null && nodeToDelete.rightChild == null)
{
nodeToDelete.leftChild = parent.leftChild;
nodeToDelete = null;
count--;
return;
}
//CASE 3: Nod has 2 children
if (nodeToDelete.rightChild != null && nodeToDelete.leftChild != null)
{
TreeNode successor = LeftMostNodeOnRight(nodeToDelete, ref parent);
TreeNode temp = new TreeNode(successor.value);
if (parent.leftChild == successor)
{
parent.leftChild = successor.rightChild;
}
else
{
parent.rightChild = successor.rightChild; nodeToDelete.value = temp.value;
}
count--;
return;
}
}

since you are using recursion , you don't need the parent Node to delete a node in a binary search tree, here is a delete method where you pass in int and the root
private BinaryTreeNode remove (int value, TreeNode t){
if(t==null)
return t; // not found; do nothing
if(value < t.value){
t.left = remove(x,y,t.left);
}
else if (value > t.value){
t.right = remove(x,y,t.right);
}
else if( t.left!=null && t.right != null) // two children
{
t.info = findMin(t.right).info;
remove(t.info.getLastName(),y,t.right);
}
else{ // one child
if (t.left != null) {
t = t.left;
}
else{
t = t.right;
}
}
return t;
}
Edit-----------findMin (find minimum node in a binary search tree)
private BinaryTreeNode findMin ( BinaryTreeNode t){ // recursive
if(t == null)
return null;
else if (t.left == null)
return t;
return findMin(t.left);
}
So you take the min value from the right subtree, and make it the parent of t.info. Follow these diagrams. We are deleting node 25 with two children.

Related

Looking for correct recursive algorithm for Leetcode 112

I am working on Leet Code problem 112. Path Sum:
Given the root of a binary tree and an integer targetSum, return true if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum.
A leaf is a node with no children.
I the code below trying to solve it, but apparently it isn't correct as I keep running into failed test cases.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root.left==null&&root.right==null&&targetSum-root.val ==0)
return true;
else{
if(root.right!= null){
hasPathSum(root.right, targetSum-root.val);
}
if(root.left!=null) {
hasPathSum(root.left, targetSum-root.val);
}
} return false;
}
}
What is wrong with this code?
You are not using the values returned by the recursive calls you make. In a verbose way, you could fix that part of your code as follows:
boolean result = false;
if (root.right != null) {
result = hasPathSum(root.right, targetSum - root.val);
}
if (!result && root.left != null) {
result = hasPathSum(root.left, targetSum - root.val);
}
return result;
It is more compact when you use more logical operators for that:
return root.right != null && hasPathSum(root.right, targetSum - root.val)
|| root.left != null && hasPathSum(root.left, targetSum - root.val);
It is not stated explicitly in the Leet Code challenge, but when calling this function on an empty tree, it should return false. So you should foresee the case where root is null.
The complete solution could look like this:
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
return root != null &&
( root.left == null && root.right == null && targetSum == root.val
|| root.right != null && hasPathSum(root.right, targetSum - root.val)
|| root.left != null && hasPathSum(root.left, targetSum - root.val)
);
}
}
Here is my recursive solution in javascript:
var hasPathSum = function(root, targetSum) {
if (root) {
if (!root.left && !root.right) {
return root.val === targetSum;
}
if (root.left) {
const isTherePath = hasPathSum(root.left, targetSum - root.val);
if (isTherePath) return true;
}
if (root.right) {
const isTherePath = hasPathSum(root.right, targetSum - root.val);
if (isTherePath) return true;
}
}
return false;
};

Recursion in Binary Search Tree construction

Below is the code implementation of binary search tree construction in C++. My confusion is I am not able to trace the recursion stack. Consider the below tree. Now I want to remove the node 10. SO this will jump to the line in the code that checks if both left and right subtree are not null and it will try to find the least value in the right subtree and that is 11 in this case. and it will recursively call remove function again . Now I have one doubt - when remove is recursively called again - first it removes 11 from that position in the original tree and return 11 from the function that is received by first remove function on the stack, but then which line in the code actually updates 11 to the root. I am really not getting this in my head. Please help me out.
10
/ \
6 12
\ / \
8 11 15
#include <bits/stdc++.h>
using namespace std;
class BST
{
public:
int value;
BST *left;
BST *right;
BST(int val)
{
value = val;
left = NULL;
right = NULL;
}
BST &insert(int val)
{
BST *currentNode = this; //this points to the current object of BST class. For instance if you created
//root node with value 10. this will store the reference to the root node object
while(true)
{
if (val < currentNode->value) //go to left subtree
{
if (currentNode->left == NULL) //if null insert
{
BST *newNode = new BST(val);
currentNode->left = newNode; //update the address
break;
}
else
{
currentNode = currentNode->left; //if not null then keep traversing
}
}
else
{
if (currentNode->right == NULL)
{
BST *newNode = new BST(val);
currentNode->right = newNode;
break;
}
else
{
currentNode = currentNode->right;
}
}
}
return *this;
}
bool contains(int val)
{
BST *currentNode = this;
while(currentNode != NULL)
{
if (val < currentNode->value)
currentNode = currentNode->left; //if value is less then keep traversing left
else if (val > currentNode->value)
currentNode = currentNode->right; //if value is greater then keep traversing right
else
return true;
}
return false;
}
BST &remove(int val, BST *parentNode = NULL)
{
BST *currentNode = this;
while (currentNode != NULL)
{
if (val < currentNode->value)
{
parentNode = currentNode;
currentNode = currentNode->left;
}
else if (val > currentNode->value)
{
parentNode = currentNode;
currentNode = currentNode->right;
}
//Up until above line the code first searches for the element to be removed
else
{
if (currentNode->left != NULL && currentNode->right != NULL) //this node checks if it has
//left and right child both and if yes then find the least value in the right subtree and then
//remove that node from that position
{
currentNode->value = currentNode->right->getMinValue();
currentNode->right->remove(currentNode->value,currentNode);
}
else if (parentNode == NULL) //this is special case of root node where there may be only
//left child existing or only right child. If both exist then above logic takes care of that
{
if (currentNode->left != NULL)
{
currentNode->value = currentNode->left->value;
currentNode->right = currentNode->left->right;
currentNode->left = currentNode->left->left;
}
else if (currentNode->right != NULL)
{
currentNode->value = currentNode->right->value;
currentNode->left = currentNode->right->left;
currentNode->right = currentNode->right->right;
}
else
{} //This is for single node tree. Do nothing
}
else if (parentNode->left == currentNode) //this condition if the parent node left child is
//the node to be removed . Then we can do simple one liner and update the node
{
parentNode->left = currentNode->left != NULL ? currentNode->left : currentNode->right;
}
else if (parentNode->right == currentNode)
{
parentNode->right = currentNode->left != NULL ? currentNode->left : currentNode->right;
}
break;
}
}
return *this;
}
int getMinValue()
{
if (left == NULL)
return value;
else
return left->getMinValue();
}
void show()
{
BST *currentNode = this;
cout<<currentNode->value;
}
};
int main()
{
int value = 10;
BST b1(value);
b1.insert(12);
b1.insert(6);
b1.insert(8);
b1.insert(15);
b1.insert(11);
b1.remove(10);
b1.show();
}

Red-Black Tree Deletion Partially Working

I implemented a red black tree in c++ with find, insert and delete. The delete only works for right side nodes and for the root node. I can't figure out why it isn't working for any of the left side nodes. Here is my code:
Node* searchNode(Node* root, int value){
Node* temp = root;
while (temp != NULL){
if (temp->val == value){
return temp;
}
else if (temp->val < value){
temp = temp->right;
}
else if (temp->val > value){
temp = temp->left;
}
}
}
Node* sibling(Node* node){
if ((node == NULL) || (node->parent == NULL)){
return NULL;
}
if (node == node->parent->left){
return node->parent->right;
}
else{
return node->parent->left;
}
}
Node* maxNode(Node* node){
while (node->right != NULL){
node = node->left;
}
return node;
}
void replaceNode(Node* old, Node* new_node){
if (old->parent == NULL){
old = new_node;
}
else{
if (old == old->parent->left){
old->parent->left = new_node;
}
else{
old->parent->right = new_node;
}
}
if (new_node != NULL){
new_node->parent = old->parent;
}
}
void deleteNode(Node* root, int value){
Node* child;
Node* temp = searchNode(root, value);
if (temp == NULL){
return;
}
if (temp->left != NULL&&temp->right != NULL){
Node* pred = maxNode(temp->right);
temp->val = pred->val;
temp = pred;
}
if (temp->left == NULL || temp->right == NULL){
if (temp->right == NULL && temp->left == NULL){
child = temp;
}
else if (temp->right == NULL){
child = temp->left;
}
else{
child = temp->right;
}
}
if (temp->color == 1){
temp->color = child->color;
delete_case1(root, child);
}
replaceNode(temp, child);
delete temp;
}
void delete_case6(Node* root, Node* n)
{
Node *s = sibling(n);
s->color = n->parent->color;
n->parent->color = 1;
if (n == n->parent->left) {
s->right->color = 1;
rotate_left(root, n->parent);
}
else {
s->left->color = 1;
rotate_right(root, n->parent);
}
}
void delete_case5(Node* root, Node* n)
{
Node *s = sibling(n);
if (s->color == 1) {
if ((n == n->parent->left) &&(s->right->color == 1) &&(s->left->color == 0)) {
s->color = 0;
s->left->color = 1;
rotate_right(root, s);
}else if ((n == n->parent->right) &&(s->left->color == 1) &&(s->right->color == 0)) {
s->color = 0;
s->right->color = 1;
rotate_left(root, s);
}
}
delete_case6(root, n);
}
void delete_case4(Node* root, Node* n)
{
Node *s = sibling(n);
if ((n->parent->color == 0) && (s->color == 1) && (s->left->color == 1) && (s->right->color == 1)) {
s->color = 0;
n->parent->color = 1;
}
else{
delete_case5(root, n);
}
}
void delete_case3(Node* root, Node* n){
Node* s = sibling(n);
if ((n->parent->color == 1) &&(s->color == 1) &&(s->left->color == 1) &&(s->right->color == 1)) {
s->color = 0;
delete_case1(root, n->parent);
}
else
delete_case4(root, n);
}
void delete_case2(Node* root, Node* n){
Node *s = sibling(n);
if (s->color == 0){
n->parent->color = 0;
s->color = 1;
if (n == n->parent->left){
rotate_left(root, n->parent);
}
else if (n == n->parent->right){
rotate_right(root, n->parent);
}
}
delete_case3(root, n);
}
void delete_case1(Node* root,Node* n){
if (n->parent != NULL){
delete_case2(root,n);
}
}
void main(){
ABTree* ABtree=new ABTree;
ABtree->root = NULL;
insertTree(ABtree->root, 15);
insertTree(ABtree->root, 8);
insertTree(ABtree->root, 2);
insertTree(ABtree->root, 9);
insertTree(ABtree->root, 10);
insertTree(ABtree->root, 12);
insertTree(ABtree->root, 18);
insertTree(ABtree->root, 25);
insertTree(ABtree->root, 20);
printTree(ABtree->root);
Node* search=searchNode(ABtree->root, 18);
cout << endl;
cout << search->val<<endl;
deleteNode(ABtree->root, 8);
printTree(ABtree->root);
}
For example if i want to delete either 8/9/2 the program crashes at delete_case4 at the if statement.
Thanks in advance!

Interview Question: Merge two sorted singly linked lists without creating new nodes

This is a programming question asked during a written test for an interview.
"You have two singly linked lists that are already sorted, you have to merge them and return a the head of the new list without creating any new extra nodes. The returned list should be sorted as well"
The method signature is:
Node MergeLists(Node list1, Node list2);
Node class is below:
class Node{
int data;
Node next;
}
I tried many solutions but not creating an extra node screws things. Please help.
Here is the accompanying blog entry http://techieme.in/merging-two-sorted-singly-linked-list/
Node MergeLists(Node list1, Node list2) {
if (list1 == null) return list2;
if (list2 == null) return list1;
if (list1.data < list2.data) {
list1.next = MergeLists(list1.next, list2);
return list1;
} else {
list2.next = MergeLists(list2.next, list1);
return list2;
}
}
Recursion should not be needed to avoid allocating a new node:
Node MergeLists(Node list1, Node list2) {
if (list1 == null) return list2;
if (list2 == null) return list1;
Node head;
if (list1.data < list2.data) {
head = list1;
} else {
head = list2;
list2 = list1;
list1 = head;
}
while(list1.next != null) {
if (list1.next.data > list2.data) {
Node tmp = list1.next;
list1.next = list2;
list2 = tmp;
}
list1 = list1.next;
}
list1.next = list2;
return head;
}
Node MergeLists(Node node1, Node node2)
{
if(node1 == null)
return node2;
else (node2 == null)
return node1;
Node head;
if(node1.data < node2.data)
{
head = node1;
node1 = node1.next;
else
{
head = node2;
node2 = node2.next;
}
Node current = head;
while((node1 != null) ||( node2 != null))
{
if (node1 == null) {
current.next = node2;
return head;
}
else if (node2 == null) {
current.next = node1;
return head;
}
if (node1.data < node2.data)
{
current.next = node1;
current = current.next;
node1 = node1.next;
}
else
{
current.next = node2;
current = current.next;
node2 = node2.next;
}
}
current.next = NULL // needed to complete the tail of the merged list
return head;
}
Look ma, no recursion!
struct llist * llist_merge(struct llist *one, struct llist *two, int (*cmp)(struct llist *l, struct llist *r) )
{
struct llist *result, **tail;
for (result=NULL, tail = &result; one && two; tail = &(*tail)->next ) {
if (cmp(one,two) <=0) { *tail = one; one=one->next; }
else { *tail = two; two=two->next; }
}
*tail = one ? one: two;
return result;
}
Here is the algorithm on how to merge two sorted linked lists A and B:
while A not empty or B not empty:
if first element of A < first element of B:
remove first element from A
insert element into C
end if
else:
remove first element from B
insert element into C
end while
Here C will be the output list.
Iteration can be done as below. Complexity = O(n)
public static LLNode mergeSortedListIteration(LLNode nodeA, LLNode nodeB) {
LLNode mergedNode ;
LLNode tempNode ;
if (nodeA == null) {
return nodeB;
}
if (nodeB == null) {
return nodeA;
}
if ( nodeA.getData() < nodeB.getData())
{
mergedNode = nodeA;
nodeA = nodeA.getNext();
}
else
{
mergedNode = nodeB;
nodeB = nodeB.getNext();
}
tempNode = mergedNode;
while (nodeA != null && nodeB != null)
{
if ( nodeA.getData() < nodeB.getData())
{
mergedNode.setNext(nodeA);
nodeA = nodeA.getNext();
}
else
{
mergedNode.setNext(nodeB);
nodeB = nodeB.getNext();
}
mergedNode = mergedNode.getNext();
}
if (nodeA != null)
{
mergedNode.setNext(nodeA);
}
if (nodeB != null)
{
mergedNode.setNext(nodeB);
}
return tempNode;
}
Node mergeList(Node h1, Node h2) {
if (h1 == null) return h2;
if (h2 == null) return h1;
Node head;
if (h1.data < h2.data) {
head = h1;
} else {
head = h2;
h2 = h1;
h1 = head;
}
while (h1.next != null && h2 != null) {
if (h1.next.data < h2.data) {
h1 = h1.next;
} else {
Node afterh2 = h2.next;
Node afterh1 = h1.next;
h1.next = h2;
h2.next = afterh1;
if (h2.next != null) {
h2 = afterh2;
}
}
}
return head;
}
This could be done without creating the extra node, with just an another Node reference passing to the parameters (Node temp).
private static Node mergeTwoLists(Node nodeList1, Node nodeList2, Node temp) {
if(nodeList1 == null) return nodeList2;
if(nodeList2 == null) return nodeList1;
if(nodeList1.data <= nodeList2.data){
temp = nodeList1;
temp.next = mergeTwoLists(nodeList1.next, nodeList2, temp);
}
else{
temp = nodeList2;
temp.next = mergeTwoLists(nodeList1, nodeList2.next, temp);
}
return temp;
}
I would like to share how i thought the solution... i saw the solution that involves recursion and they are pretty amazing, is the outcome of well functional and modular thinking. I really appreciate the sharing.
I would like to add that recursion won't work for big lits, the stack calls will overflow; so i decided to try the iterative approach... and this is what i get.
The code is pretty self explanatory, i added some inline comments to try to assure this.
If you don't get it, please notify me and i will improve the readability (perhaps i am having a misleading interpretation of my own code).
import java.util.Random;
public class Solution {
public static class Node<T extends Comparable<? super T>> implements Comparable<Node<T>> {
T data;
Node next;
#Override
public int compareTo(Node<T> otherNode) {
return data.compareTo(otherNode.data);
}
#Override
public String toString() {
return ((data != null) ? data.toString() + ((next != null) ? "," + next.toString() : "") : "null");
}
}
public static Node merge(Node firstLeft, Node firstRight) {
combine(firstLeft, firstRight);
return Comparision.perform(firstLeft, firstRight).min;
}
private static void combine(Node leftNode, Node rightNode) {
while (leftNode != null && rightNode != null) {
// get comparision data about "current pair of nodes being analized".
Comparision comparision = Comparision.perform(leftNode, rightNode);
// stores references to the next nodes
Node nextLeft = leftNode.next;
Node nextRight = rightNode.next;
// set the "next node" of the "minor node" between the "current pair of nodes being analized"...
// ...to be equals the minor node between the "major node" and "the next one of the minor node" of the former comparision.
comparision.min.next = Comparision.perform(comparision.max, comparision.min.next).min;
if (comparision.min == leftNode) {
leftNode = nextLeft;
} else {
rightNode = nextRight;
}
}
}
/** Stores references to two nodes viewed as one minimum and one maximum. The static factory method populates properly the instance being build */
private static class Comparision {
private final Node min;
private final Node max;
private Comparision(Node min, Node max) {
this.min = min;
this.max = max;
}
private static Comparision perform(Node a, Node b) {
Node min, max;
if (a != null && b != null) {
int comparision = a.compareTo(b);
if (comparision <= 0) {
min = a;
max = b;
} else {
min = b;
max = a;
}
} else {
max = null;
min = (a != null) ? a : b;
}
return new Comparision(min, max);
}
}
// Test example....
public static void main(String args[]) {
Node firstLeft = buildList(20);
Node firstRight = buildList(40);
Node firstBoth = merge(firstLeft, firstRight);
System.out.println(firstBoth);
}
// someone need to write something like this i guess...
public static Node buildList(int size) {
Random r = new Random();
Node<Integer> first = new Node<>();
first.data = 0;
first.next = null;
Node<Integer> current = first;
Integer last = first.data;
for (int i = 1; i < size; i++) {
Node<Integer> node = new Node<>();
node.data = last + r.nextInt(5);
last = node.data;
node.next = null;
current.next = node;
current = node;
}
return first;
}
}
A simple iterative solution.
Node* MergeLists(Node* A, Node* B)
{
//handling the corner cases
//if both lists are empty
if(!A && !B)
{
cout << "List is empty" << endl;
return 0;
}
//either of list is empty
else if(!A) return B;
else if(!B) return A;
else
{
Node* head = NULL;//this will be the head of the newList
Node* previous = NULL;//this will act as the
/* In this algorithm we will keep the
previous pointer that will point to the last node of the output list.
And, as given we have A & B as pointer to the given lists.
The algorithm will keep on going untill either one of the list become empty.
Inside of the while loop, it will divide the algorithm in two parts:
- First, if the head of the output list is not obtained yet
- Second, if head is already there then we will just compare the values and keep appending to the 'previous' pointer.
When one of the list become empty we will append the other 'left over' list to the output list.
*/
while(A && B)
{
if(!head)
{
if(A->data <= B->data)
{
head = A;//setting head of the output list to A
previous = A; //initializing previous
A = A->next;
}
else
{
head = B;//setting head of the output list to B
previous = B;//initializing previous
B = B->next;
}
}
else//when head is already set
{
if(A->data <= B->data)
{
if(previous->next != A)
previous->next = A;
A = A->next;//Moved A forward but keeping B at the same position
}
else
{
if(previous->next != B)
previous->next = B;
B = B->next; //Moved B forward but keeping A at the same position
}
previous = previous->next;//Moving the Output list pointer forward
}
}
//at the end either one of the list would finish
//and we have to append the other list to the output list
if(!A)
previous->next = B;
if(!B)
previous->next = A;
return head; //returning the head of the output list
}
}
I show below an iterative solution. A recursive solution would be more compact, but since we don't know the length of the lists, recursion runs the risk of stack overflow.
The basic idea is similar to the merge step in merge sort; we keep a pointer corresponding to each input list; at each iteration, we advance the pointer corresponding to the smaller element. However, there's one crucial difference where most people get tripped. In merge sort, since we use a result array, the next position to insert is always the index of the result array. For a linked list, we need to keep a pointer to the last element of the sorted list. The pointer may jump around from one input list to another depending on which one has the smaller element for the current iteration.
With that, the following code should be self-explanatory.
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) {
return l2;
}
if (l2 == null) {
return l1;
}
ListNode first = l1;
ListNode second = l2;
ListNode head = null;
ListNode last = null;
while (first != null && second != null) {
if (first.val < second.val) {
if (last != null) {
last.next = first;
}
last = first;
first = first.next;
} else {
if (last != null) {
last.next = second;
}
last = second;
second = second.next;
}
if (head == null) {
head = last;
}
}
if (first == null) {
last.next = second;
}
if (second == null) {
last.next = first;
}
return head;
}
Simple code in javascript to merge two linked list inplace.
function mergeLists(l1, l2) {
let head = new ListNode(0); //dummy
let curr = head;
while(l1 && l2) {
if(l2.val >= l1.val) {
curr.next = l1;
l1 = l1.next;
} else {
curr.next = l2;
l2=l2.next
}
curr = curr.next;
}
if(!l1){
curr.next=l2;
}
if(!l2){
curr.next=l1;
}
return head.next;
}
First of all understand the mean of "without creating any new extra nodes", As I understand it does not mean that I can not have pointer(s) which points to an existing node(s).
You can not achieve it without talking pointers to existing nodes, even if you use recursion to achieve the same, system will create pointers for you as call stacks. It is just like telling system to add pointers which you have avoided in your code.
Simple function to achieve the same with taking extra pointers:
typedef struct _LLNode{
int value;
struct _LLNode* next;
}LLNode;
LLNode* CombineSortedLists(LLNode* a,LLNode* b){
if(NULL == a){
return b;
}
if(NULL == b){
return a;
}
LLNode* root = NULL;
if(a->value < b->value){
root = a;
a = a->next;
}
else{
root = b;
b = b->next;
}
LLNode* curr = root;
while(1){
if(a->value < b->value){
curr->next = a;
curr = a;
a=a->next;
if(NULL == a){
curr->next = b;
break;
}
}
else{
curr->next = b;
curr = b;
b=b->next;
if(NULL == b){
curr->next = a;
break;
}
}
}
return root;
}
Node * merge_sort(Node *a, Node *b){
Node *result = NULL;
if(a == NULL)
return b;
else if(b == NULL)
return a;
/* For the first node, we would set the result to either a or b */
if(a->data <= b->data){
result = a;
/* Result's next will point to smaller one in lists
starting at a->next and b */
result->next = merge_sort(a->next,b);
}
else {
result = b;
/*Result's next will point to smaller one in lists
starting at a and b->next */
result->next = merge_sort(a,b->next);
}
return result;
}
Please refer to my blog post for http://www.algorithmsandme.com/2013/10/linked-list-merge-two-sorted-linked.html
Node MergeLists(Node list1, Node list2) {
//if list is null return other list
if(list1 == null)
{
return list2;
}
else if(list2 == null)
{
return list1;
}
else
{
Node head;
//Take head pointer to the node which has smaller first data node
if(list1.data < list2.data)
{
head = list1;
list1 = list1.next;
}
else
{
head = list2;
list2 = list2.next;
}
Node current = head;
//loop till both list are not pointing to null
while(list1 != null || list2 != null)
{
//if list1 is null, point rest of list2 by current pointer
if(list1 == null){
current.next = list2;
return head;
}
//if list2 is null, point rest of list1 by current pointer
else if(list2 == null){
current.next = list1;
return head;
}
//compare if list1 node data is smaller than list2 node data, list1 node will be
//pointed by current pointer
else if(list1.data < list2.data)
{
current.next = list1;
current = current.next;
list1 = list1.next;
}
else
{
current.next = list2;
current = current.next;
list2 = list2.next;
}
}
return head;
}
}
Here is a complete working example that uses the linked list implemented java.util. You can just copy paste the code below inside a main() method.
LinkedList<Integer> dList1 = new LinkedList<Integer>();
LinkedList<Integer> dList2 = new LinkedList<Integer>();
LinkedList<Integer> dListMerged = new LinkedList<Integer>();
dList1.addLast(1);
dList1.addLast(8);
dList1.addLast(12);
dList1.addLast(15);
dList1.addLast(85);
dList2.addLast(2);
dList2.addLast(3);
dList2.addLast(12);
dList2.addLast(24);
dList2.addLast(85);
dList2.addLast(185);
int i = 0;
int y = 0;
int dList1Size = dList1.size();
int dList2Size = dList2.size();
int list1Item = dList1.get(i);
int list2Item = dList2.get(y);
while (i < dList1Size || y < dList2Size) {
if (i < dList1Size) {
if (list1Item <= list2Item || y >= dList2Size) {
dListMerged.addLast(list1Item);
i++;
if (i < dList1Size) {
list1Item = dList1.get(i);
}
}
}
if (y < dList2Size) {
if (list2Item <= list1Item || i >= dList1Size) {
dListMerged.addLast(list2Item);
y++;
if (y < dList2Size) {
list2Item = dList2.get(y);
}
}
}
}
for(int x:dListMerged)
{
System.out.println(x);
}
Recursive way(variant of Stefan answer)
MergeList(Node nodeA, Node nodeB ){
if(nodeA==null){return nodeB};
if(nodeB==null){return nodeA};
if(nodeB.data<nodeA.data){
Node returnNode = MergeNode(nodeA,nodeB.next);
nodeB.next = returnNode;
retturn nodeB;
}else{
Node returnNode = MergeNode(nodeA.next,nodeB);
nodeA.next=returnNode;
return nodeA;
}
Consider below linked list to visualize this
2>4 list A
1>3 list B
Almost same answer(non recursive) as Stefan but with little more comments/meaningful variable name. Also covered double linked list in comments if someone is interested
Consider the example
5->10->15>21 // List1
2->3->6->20 //List2
Node MergeLists(List list1, List list2) {
if (list1 == null) return list2;
if (list2 == null) return list1;
if(list1.head.data>list2.head.data){
listB =list2; // loop over this list as its head is smaller
listA =list1;
} else {
listA =list2; // loop over this list
listB =list1;
}
listB.currentNode=listB.head;
listA.currentNode=listA.head;
while(listB.currentNode!=null){
if(listB.currentNode.data<listA.currentNode.data){
Node insertFromNode = listB.currentNode.prev;
Node startingNode = listA.currentNode;
Node temp = inserFromNode.next;
inserFromNode.next = startingNode;
startingNode.next=temp;
startingNode.next.prev= startingNode; // for doubly linked list
startingNode.prev=inserFromNode; // for doubly linked list
listB.currentNode= listB.currentNode.next;
listA.currentNode= listA.currentNode.next;
}
else
{
listB.currentNode= listB.currentNode.next;
}
}
My take on the question is as below:
Pseudocode:
Compare the two heads A and B.
If A <= B, then add A and move the head of A to the next node.
Similarly, if B < A, then add B and move the head of B to the next node B.
If both A and B are NULL then stop and return.
If either of them is NULL, then traverse the non null head till it becomes NULL.
Code:
public Node mergeLists(Node headA, Node headB) {
Node merge = null;
// If we have reached the end, then stop.
while (headA != null || headB != null) {
// if B is null then keep appending A, else check if value of A is lesser or equal than B
if (headB == null || (headA != null && headA.data <= headB.data)) {
// Add the new node, handle addition separately in a new method.
merge = add(merge, headA.data);
// Since A is <= B, Move head of A to next node
headA = headA.next;
// if A is null then keep appending B, else check if value of B is lesser than A
} else if (headA == null || (headB != null && headB.data < headA.data)) {
// Add the new node, handle addition separately in a new method.
merge = add(merge, headB.data);
// Since B is < A, Move head of B to next node
headB = headB.next;
}
}
return merge;
}
public Node add(Node head, int data) {
Node end = new Node(data);
if (head == null) {
return end;
}
Node curr = head;
while (curr.next != null) {
curr = curr.next;
}
curr.next = end;
return head;
}
/* Simple/Elegant Iterative approach in Java*/
private static LinkedList mergeLists(LinkedList list1, LinkedList list2) {
Node head1 = list1.start;
Node head2 = list2.start;
if (list1.size == 0)
return list2;
if (list2.size == 0)
return list1;
LinkedList mergeList = new LinkedList();
while (head1 != null && head2 != null) {
if (head1.getData() < head2.getData()) {
int data = head1.getData();
mergeList.insert(data);
head1 = head1.getNext();
} else {
int data = head2.getData();
mergeList.insert(data);
head2 = head2.getNext();
}
}
while (head1 != null) {
int data = head1.getData();
mergeList.insert(data);
head1 = head1.getNext();
}
while (head2 != null) {
int data = head2.getData();
mergeList.insert(data);
head2 = head2.getNext();
}
return mergeList;
}
/* Build-In singly LinkedList class in Java*/
class LinkedList {
Node start;
int size = 0;
void insert(int data) {
if (start == null)
start = new Node(data);
else {
Node temp = start;
while (temp.getNext() != null) {
temp = temp.getNext();
}
temp.setNext(new Node(data));
}
size++;
}
#Override
public String toString() {
String str = "";
Node temp=start;
while (temp != null) {
str += temp.getData() + "-->";
temp = temp.getNext();
}
return str;
}
}
LLNode *mergeSorted(LLNode *h1, LLNode *h2)
{
LLNode *h3=NULL;
LLNode *h3l;
if(h1==NULL && h2==NULL)
return NULL;
if(h1==NULL)
return h2;
if(h2==NULL)
return h1;
if(h1->data<h2->data)
{
h3=h1;
h1=h1->next;
}
else
{
h3=h2;
h2=h2->next;
}
LLNode *oh=h3;
while(h1!=NULL && h2!=NULL)
{
if(h1->data<h2->data)
{
h3->next=h1;
h3=h3->next;
h1=h1->next;
}
else
{
h3->next=h2;
h3=h3->next;
h2=h2->next;
}
}
if(h1==NULL)
h3->next=h2;
if(h2==NULL)
h3->next=h1;
return oh;
}
// Common code for insert at the end
private void insertEnd(int data) {
Node newNode = new Node(data);
if (head == null) {
newNode.next = head;
head = tail = newNode;
return;
}
Node tempNode = tail;
tempNode.next = newNode;
tail = newNode;
}
private void mergerTwoSortedListInAscOrder(Node tempNode1, Node tempNode2) {
if (tempNode1 == null && tempNode2 == null)
return;
if (tempNode1 == null) {
head3 = tempNode2;
return;
}
if (tempNode2 == null) {
head3 = tempNode1;
return;
}
while (tempNode1 != null && tempNode2 != null) {
if (tempNode1.mData < tempNode2.mData) {
insertEndForHead3(tempNode1.mData);
tempNode1 = tempNode1.next;
} else if (tempNode1.mData > tempNode2.mData) {
insertEndForHead3(tempNode2.mData);
tempNode2 = tempNode2.next;
} else {
insertEndForHead3(tempNode1.mData);
insertEndForHead3(tempNode2.mData);
tempNode1 = tempNode1.next;
tempNode2 = tempNode2.next;
}
}
if (tempNode1 != null) {
while (tempNode1 != null) {
insertEndForHead3(tempNode1.mData);
tempNode1 = tempNode1.next;
}
}
if (tempNode2 != null) {
while (tempNode2 != null) {
insertEndForHead3(tempNode2.mData);
tempNode2 = tempNode2.next;
}
}
}
:)GlbMP
public static Node merge(Node h1, Node h2) {
Node h3 = new Node(0);
Node current = h3;
boolean isH1Left = false;
boolean isH2Left = false;
while (h1 != null || h2 != null) {
if (h1.data <= h2.data) {
current.next = h1;
h1 = h1.next;
} else {
current.next = h2;
h2 = h2.next;
}
current = current.next;
if (h2 == null && h1 != null) {
isH1Left = true;
break;
}
if (h1 == null && h2 != null) {
isH2Left = true;
break;
}
}
if (isH1Left) {
while (h1 != null) {
current.next = h1;
current = current.next;
h1 = h1.next;
}
}
if (isH2Left) {
while (h2 != null) {
current.next = h2;
current = current.next;
h2 = h2.next;
}
}
h3 = h3.next;
return h3;
}
I created only one dummy node at the beginning to save myself many 'if' conditions.
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode list1Cursor = l1;
ListNode list2Cursor = l2;
ListNode currentNode = new ListNode(-1); // Dummy node
ListNode head = currentNode;
while (list1Cursor != null && list2Cursor != null)
{
if (list1Cursor.val < list2Cursor.val) {
currentNode.next = list1Cursor;
list1Cursor = list1Cursor.next;
currentNode = currentNode.next;
} else {
currentNode.next = list2Cursor;
list2Cursor = list2Cursor.next;
currentNode = currentNode.next;
}
}
// Complete the rest
while (list1Cursor != null) {
currentNode.next = list1Cursor;
currentNode = currentNode.next;
list1Cursor = list1Cursor.next;
}
while (list2Cursor != null) {
currentNode.next = list2Cursor;
currentNode = currentNode.next;
list2Cursor = list2Cursor.next;
}
return head.next;
}
public ListNode MergeTwoLists(ListNode l1, ListNode l2) {//c#
ListNode _destNode=null;//Merged List
ListNode _srcNode=null;
ListNode _resHead=null;
if(l1==null || l2==null){//for scenario l1 null or l2 null or both null
return l1??l2??null;
}
if(l1.val<=l2.val){
_destNode=l1;//finding the dest list
_srcNode=l2;
_resHead=l1;
}
else{
_destNode=l2;
_srcNode=l1;
_resHead=l2;
}
while(_destNode!=null && _srcNode!=null){
if(_destNode.val<=_srcNode.val && (_destNode.next==null ||_destNode.next.val>=_srcNode.val)) {
//appending the values to dest list , if the element from dest list is less than element from _srcNode
var _temp_l2_currentnode=_srcNode;
_srcNode=_srcNode.next;
var _temp_l1_nextnode=_destNode.next;
_destNode.next=_temp_l2_currentnode;
_temp_l2_currentnode.next=_temp_l1_nextnode;
_destNode=_destNode.next;
}
else{
_destNode=_destNode.next;
}
}
return _resHead;
}
private static Node mergeLists(Node L1, Node L2) {
Node P1 = L1.val < L2.val ? L1 : L2;
Node P2 = L1.val < L2.val ? L2 : L1;
Node BigListHead = P1;
Node tempNode = null;
while (P1 != null && P2 != null) {
if (P1.next != null && P1.next.val >P2.val) {
tempNode = P1.next;
P1.next = P2;
P1 = P2;
P2 = tempNode;
} else if(P1.next != null)
P1 = P1.next;
else {
P1.next = P2;
break;
}
}
return BigListHead;
}
void printLL(){
NodeLL cur = head;
if(cur.getNext() == null){
System.out.println("LL is emplty");
}else{
//System.out.println("printing Node");
while(cur.getNext() != null){
cur = cur.getNext();
System.out.print(cur.getData()+ " ");
}
}
System.out.println();
}
void mergeSortedList(NodeLL node1, NodeLL node2){
NodeLL cur1 = node1.getNext();
NodeLL cur2 = node2.getNext();
NodeLL cur = head;
if(cur1 == null){
cur = node2;
}
if(cur2 == null){
cur = node1;
}
while(cur1 != null && cur2 != null){
if(cur1.getData() <= cur2.getData()){
cur.setNext(cur1);
cur1 = cur1.getNext();
}
else{
cur.setNext(cur2);
cur2 = cur2.getNext();
}
cur = cur.getNext();
}
while(cur1 != null){
cur.setNext(cur1);
cur1 = cur1.getNext();
cur = cur.getNext();
}
while(cur2 != null){
cur.setNext(cur2);
cur2 = cur2.getNext();
cur = cur.getNext();
}
printLL();
}
Here is the code on how to merge two sorted linked lists headA and headB:
Node* MergeLists1(Node *headA, Node* headB)
{
Node *p = headA;
Node *q = headB;
Node *result = NULL;
Node *pp = NULL;
Node *qq = NULL;
Node *head = NULL;
int value1 = 0;
int value2 = 0;
if((headA == NULL) && (headB == NULL))
{
return NULL;
}
if(headA==NULL)
{
return headB;
}
else if(headB==NULL)
{
return headA;
}
else
{
while((p != NULL) || (q != NULL))
{
if((p != NULL) && (q != NULL))
{
int value1 = p->data;
int value2 = q->data;
if(value1 <= value2)
{
pp = p->next;
p->next = NULL;
if(result == NULL)
{
head = result = p;
}
else
{
result->next = p;
result = p;
}
p = pp;
}
else
{
qq = q->next;
q->next = NULL;
if(result == NULL)
{
head = result = q;
}
else
{
result->next = q;
result = q;
}
q = qq;
}
}
else
{
if(p != NULL)
{
pp = p->next;
p->next = NULL;
result->next = p;
result = p;
p = pp;
}
if(q != NULL)
{
qq = q->next;
q->next = NULL;
result->next = q;
result = q;
q = qq;
}
}
}
}
return head;
}

How do you validate a binary search tree?

I read on here of an exercise in interviews known as validating a binary search tree.
How exactly does this work? What would one be looking for in validating a binary search tree? I have written a basic search tree, but never heard of this concept.
Actually that is the mistake everybody does in an interview.
Leftchild must be checked against (minLimitof node,node.value)
Rightchild must be checked against (node.value,MaxLimit of node)
IsValidBST(root,-infinity,infinity);
bool IsValidBST(BinaryNode node, int MIN, int MAX)
{
if(node == null)
return true;
if(node.element > MIN
&& node.element < MAX
&& IsValidBST(node.left,MIN,node.element)
&& IsValidBST(node.right,node.element,MAX))
return true;
else
return false;
}
Another solution (if space is not a constraint):
Do an inorder traversal of the tree and store the node values in an array. If the array is in sorted order, its a valid BST otherwise not.
"Validating" a binary search tree means that you check that it does indeed have all smaller items on the left and large items on the right. Essentially, it's a check to see if a binary tree is a binary search tree.
The best solution I found is O(n) and it uses no extra space. It is similar to inorder traversal but instead of storing it to array and then checking whether it is sorted we can take a static variable and check while inorder traversing whether array is sorted.
static struct node *prev = NULL;
bool isBST(struct node* root)
{
// traverse the tree in inorder fashion and keep track of prev node
if (root)
{
if (!isBST(root->left))
return false;
// Allows only distinct valued nodes
if (prev != NULL && root->data <= prev->data)
return false;
prev = root;
return isBST(root->right);
}
return true;
}
Iterative solution using inorder traversal.
bool is_bst(Node *root) {
if (!root)
return true;
std::stack<Node*> stack;
bool started = false;
Node *node = root;
int prev_val;
while(true) {
if (node) {
stack.push(node);
node = node->left();
continue;
}
if (stack.empty())
break;
node = stack.top();
stack.pop();
/* beginning of bst check */
if(!started) {
prev_val = node->val();
started = true;
} else {
if (prev_val > node->val())
return false;
prev_val = node->val();
}
/* end of bst check */
node = node->right();
}
return true;
}
Here is my solution in Clojure:
(defstruct BST :val :left :right)
(defn in-order [bst]
(when-let [{:keys [val, left, right]} bst]
(lazy-seq
(concat (in-order left) (list val) (in-order right)))))
(defn is-strictly-sorted? [col]
(every?
(fn [[a b]] (< a b))
(partition 2 1 col)))
(defn is-valid-BST [bst]
(is-strictly-sorted? (in-order bst)))
Since the in-order traversal of a BST is a non-decrease sequence, we could use this property to judge whether a binary tree is BST or not. Using Morris traversal and maintaining the pre node, we could get a solution in O(n) time and O(1) space complexity. Here is my code
public boolean isValidBST(TreeNode root) {
TreeNode pre = null, cur = root, tmp;
while(cur != null) {
if(cur.left == null) {
if(pre != null && pre.val >= cur.val)
return false;
pre = cur;
cur = cur.right;
}
else {
tmp = cur.left;
while(tmp.right != null && tmp.right != cur)
tmp = tmp.right;
if(tmp.right == null) { // left child has not been visited
tmp.right = cur;
cur = cur.left;
}
else { // left child has been visited already
tmp.right = null;
if(pre != null && pre.val >= cur.val)
return false;
pre = cur;
cur = cur.right;
}
}
}
return true;
}
bool BinarySearchTree::validate() {
int minVal = -1;
int maxVal = -1;
return ValidateImpl(root, minVal, maxVal);
}
bool BinarySearchTree::ValidateImpl(Node *currRoot, int &minVal, int &maxVal)
{
int leftMin = -1;
int leftMax = -1;
int rightMin = -1;
int rightMax = -1;
if (currRoot == NULL) return true;
if (currRoot->left) {
if (currRoot->left->value < currRoot->value) {
if (!ValidateImpl(currRoot->left, leftMin, leftMax)) return false;
if (leftMax != currRoot->left->value && currRoot->value < leftMax) return false;
}
else
return false;
} else {
leftMin = leftMax = currRoot->value;
}
if (currRoot->right) {
if (currRoot->right->value > currRoot->value) {
if(!ValidateImpl(currRoot->right, rightMin, rightMax)) return false;
if (rightMin != currRoot->right->value && currRoot->value > rightMin) return false;
}
else return false;
} else {
rightMin = rightMax = currRoot->value;
}
minVal = leftMin < rightMin ? leftMin : rightMin;
maxVal = leftMax > rightMax ? leftMax : rightMax;
return true;
}
"It's better to define an invariant first. Here the invariant is -- any two sequential elements of the BST in the in-order traversal must be in strictly increasing order of their appearance (can't be equal, always increasing in in-order traversal). So solution can be just a simple in-order traversal with remembering the last visited node and comparison the current node against the last visited one to '<' (or '>')."
I got this question in a phone interview recently and struggled with it more than I should have. I was trying to keep track of minimums and maximums in child nodes and I just couldn't wrap my brain around the different cases under the pressure of an interview.
After thinking about it while falling asleep last night, I realized that it is as simple as keeping track of the last node you've visited during an inorder traversal. In Java:
public <T extends Comparable<T>> boolean isBst(TreeNode<T> root) {
return isBst(root, null);
}
private <T extends Comparable<T>> boolean isBst(TreeNode<T> node, TreeNode<T> prev) {
if (node == null)
return true;
if (isBst(node.left, prev) && (prev == null || prev.compareTo(node) < 0 ))
return isBst(node.right, node);
return false;
}
In Java and allowing nodes with same value in either sub-tree:
public boolean isValid(Node node) {
return isValid(node, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
private boolean isValid(Node node, int minLimit, int maxLimit) {
if (node == null)
return true;
return minLimit <= node.value && node.value <= maxLimit
&& isValid(node.left, minLimit, node.value)
&& isValid(node.right, node.value, maxLimit);
}
Here is my answer in python, it has all the corner cases addressed and well tested in hackerrank website
""" Node is defined as
class node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
"""
def checkBST(root):
return checkLeftSubTree(root, root.left) and checkRightSubTree(root, root.right)
def checkLeftSubTree(root, subTree):
if not subTree:
return True
else:
return root.data > subTree.data \
and checkLeftSubTree(root, subTree.left) \
and checkLeftSubTree(root, subTree.right) \
and checkLeftSubTree(subTree, subTree.left) \
and checkRightSubTree(subTree, subTree.right)
def checkRightSubTree(root, subTree):
if not subTree:
return True
else:
return root.data < subTree.data \
and checkRightSubTree(root, subTree.left) \
and checkRightSubTree(root, subTree.right) \
and checkRightSubTree(subTree, subTree.right) \
and checkLeftSubTree(subTree, subTree.left)
// using inorder traverse based Impl
bool BinarySearchTree::validate() {
int val = -1;
return ValidateImpl(root, val);
}
// inorder traverse based Impl
bool BinarySearchTree::ValidateImpl(Node *currRoot, int &val) {
if (currRoot == NULL) return true;
if (currRoot->left) {
if (currRoot->left->value > currRoot->value) return false;
if(!ValidateImpl(currRoot->left, val)) return false;
}
if (val > currRoot->value) return false;
val = currRoot->value;
if (currRoot->right) {
if (currRoot->right->value < currRoot->value) return false;
if(!ValidateImpl(currRoot->right, val)) return false;
}
return true;
}
bool ValidateBST(Node *pCurrentNode, int nMin = INT_MIN, int nMax = INT_MAX)
{
return
(
pCurrentNode == NULL
)
||
(
(
!pCurrentNode->pLeftNode ||
(
pCurrentNode->pLeftNode->value < pCurrentNode->value &&
pCurrentNode->pLeftNode->value < nMax &&
ValidateBST(pCurrentNode->pLeftNode, nMin, pCurrentNode->value)
)
)
&&
(
!pCurrentNode->pRightNode ||
(
pCurrentNode->pRightNode->value > pCurrentNode->value &&
pCurrentNode->pRightNode->value > nMin &&
ValidateBST(pCurrentNode->pRightNode, pCurrentNode->value, nMax)
)
)
);
}
To find out whether given BT is BST for any datatype, you need go with below approach.
1. call recursive function till the end of leaf node using inorder traversal
2. Build your min and max values yourself.
Tree element must have less than / greater than operator defined.
#define MIN (FirstVal, SecondVal) ((FirstVal) < (SecondVal)) ? (FirstVal):(SecondVal)
#define MAX (FirstVal, SecondVal) ((FirstVal) > (SecondVal)) ? (FirstVal):(SecondVal)
template <class T>
bool IsValidBST (treeNode &root)
{
T min, max;
return IsValidBST (root, &min, &max);
}
template <class T>
bool IsValidBST (treeNode *root, T *MIN , T *MAX)
{
T leftMin, leftMax, rightMin, rightMax;
bool isValidBST;
if (root->leftNode == NULL && root->rightNode == NULL)
{
*MIN = root->element;
*MAX = root->element;
return true;
}
isValidBST = IsValidBST (root->leftNode, &leftMin, &leftMax);
if (isValidBST)
isValidBST = IsValidBST (root->rightNode, &rightMin, &rightMax);
if (isValidBST)
{
*MIN = MIN (leftMIN, rightMIN);
*Max = MAX (rightMax, leftMax);
}
return isValidBST;
}
bool isBST(struct node* root)
{
static struct node *prev = NULL;
// traverse the tree in inorder fashion and keep track of prev node
if (root)
{
if (!isBST(root->left))
return false;
// Allows only distinct valued nodes
if (prev != NULL && root->data <= prev->data)
return false;
prev = root;
return isBST(root->right);
}
return true;
}
Works Fine :)
Recursion is easy but iterative approach is better, there is one iterative version above but it's way too complex than necessary. Here is the best solution in c++ you'll ever find anywhere:
This algorithm runs in O(N) time and needs O(lgN) space.
struct TreeNode
{
int value;
TreeNode* left;
TreeNode* right;
};
bool isBST(TreeNode* root) {
vector<TreeNode*> stack;
TreeNode* prev = nullptr;
while (root || stack.size()) {
if (root) {
stack.push_back(root);
root = root->left;
} else {
if (prev && stack.back()->value <= prev->value)
return false;
prev = stack.back();
root = prev->right;
stack.pop_back();
}
}
return true;
}
I wrote a solution to use inorder Traversal BST and check whether the nodes is
increasing order for space O(1) AND time O(n). TreeNode predecessor is prev node. I am not sure the solution is right or not. Because the inorder Traversal can not define a whole tree.
public boolean isValidBST(TreeNode root, TreeNode predecessor) {
boolean left = true, right = true;
if (root.left != null) {
left = isValidBST(root.left, predecessor);
}
if (!left)
return false;
if (predecessor.val > root.val)
return false;
predecessor.val = root.val;
if (root.right != null) {
right = isValidBST(root.right, predecessor);
}
if (!right)
return false;
return true;
}
Following is the Java implementation of BST validation, where we travel the tree in-order DFS and it returns false if we get any number which is greater than last number.
static class BSTValidator {
private boolean lastNumberInitialized = false;
private int lastNumber = -1;
boolean isValidBST(TreeNode node) {
if (node.left != null && !isValidBST(node.left)) return false;
// In-order visiting should never see number less than previous
// in valid BST.
if (lastNumberInitialized && (lastNumber > node.getData())) return false;
if (!lastNumberInitialized) lastNumberInitialized = true;
lastNumber = node.getData();
if (node.right != null && !isValidBST(node.right)) return false;
return true;
}
}
Recursive solution:
isBinary(root)
{
if root == null
return true
else if( root.left == NULL and root.right == NULL)
return true
else if(root.left == NULL)
if(root.right.element > root.element)
rerturn isBInary(root.right)
else if (root.left.element < root.element)
return isBinary(root.left)
else
return isBInary(root.left) and isBinary(root.right)
}
Iterative solution.
private static boolean checkBst(bst node) {
Stack<bst> s = new Stack<bst>();
bst temp;
while(node!=null){
s.push(node);
node=node.left;
}
while (!s.isEmpty()){
node = s.pop();
System.out.println(node.val);
temp = node;
if(node.right!=null){
node = node.right;
while(node!=null)
{
//Checking if the current value is lesser than the previous value and ancestor.
if(node.val < temp.val)
return false;
if(!s.isEmpty())
if(node.val>s.peek().val)
return false;
s.push(node);
if(node!=null)
node=node.left;
}
}
}
return true;
}
This works for duplicates.
// time O(n), space O(logn)
// pseudocode
is-bst(node, min = int.min, max = int.max):
if node == null:
return true
if node.value <= min || max < node.value:
return false
return is-bst(node.left, min, node.value)
&& is-bst(node.right, node.value, max)
This works even for int.min and int.max values using Nullable types.
// time O(n), space O(logn)
// pseudocode
is-bst(node, min = null, max = null):
if node == null:
return true
if min != null && node.value <= min
return false
if max != null && max < node.value:
return false
return is-bst(node.left, min, node.value)
&& is-bst(node.right, node.value, max)
Inspired by http://www.jiuzhang.com/solutions/validate-binary-search-tree/
There are two general solutions: traversal and divide && conquer.
public class validateBinarySearchTree {
public boolean isValidBST(TreeNode root) {
return isBSTTraversal(root) && isBSTDivideAndConquer(root);
}
// Solution 1: Traversal
// The inorder sequence of a BST is a sorted ascending list
private int lastValue = 0; // the init value of it doesn't matter.
private boolean firstNode = true;
public boolean isBSTTraversal(TreeNode root) {
if (root == null) {
return true;
}
if (!isValidBST(root.left)) {
return false;
}
// firstNode is needed because of if firstNode is Integer.MIN_VALUE,
// even if we set lastValue to Integer.MIN_VALUE, it will still return false
if (!firstNode && lastValue >= root.val) {
return false;
}
firstNode = false;
lastValue = root.val;
if (!isValidBST(root.right)) {
return false;
}
return true;
}
// Solution 2: divide && conquer
private class Result {
int min;
int max;
boolean isBST;
Result(int min, int max, boolean isBST) {
this.min = min;
this.max = max;
this.isBST = isBST;
}
}
public boolean isBSTDivideAndConquer(TreeNode root) {
return isBSTHelper(root).isBST;
}
public Result isBSTHelper(TreeNode root) {
// For leaf node's left or right
if (root == null) {
// we set min to Integer.MAX_VALUE and max to Integer.MIN_VALUE
// because of in the previous level which is the leaf level,
// we want to set the min or max to that leaf node's val (in the last return line)
return new Result(Integer.MAX_VALUE, Integer.MIN_VALUE, true);
}
Result left = isBSTHelper(root.left);
Result right = isBSTHelper(root.right);
if (!left.isBST || !right.isBST) {
return new Result(0,0, false);
}
// For non-leaf node
if (root.left != null && left.max >= root.val
&& root.right != null && right.min <= root.val) {
return new Result(0, 0, false);
}
return new Result(Math.min(left.min, root.val),
Math.max(right.max, root.val), true);
}
}
One liner
bool is_bst(Node *root, int from, int to) {
return (root == NULL) ? true :
root->val >= from && root->val <= to &&
is_bst(root->left, from, root->val) &&
is_bst(root->right, root->val, to);
}
Pretty long line though.
Here's a solution in java from sedgewick's algorithm class.
Check the full BST implementation here
I added some explanatory comments
private boolean isBST() {
return isBST(root, null, null);
}
private boolean isBST(Node x, Key min, Key max) {
if (x == null) return true;
// when checking right subtree min is key of x's parent
if (min != null && x.key.compareTo(min) <= 0) return false;
// when checking left subtree, max is key of x's parent
if (max != null && x.key.compareTo(max) >= 0) return false;
// check left subtree and right subtree
return isBST(x.left, min, x.key) && isBST(x.right, x.key, max);
}
The iterative function checks iteratively whether given tree is a binary search tree.
The recurse function checks recursively whether given tree is a binary search tree or not.
In iterative function I use bfs for checking BST.
In recurse function I use dfs for checking BST.
Both solutions have a time complexity of O(n)
iterative solution has an advantage over recurse solution and that is iterative solution does early stopping.
Even recurse function can be optimized for early stopping by global flag value.
The idea of both the solution is that the left child should be within the range of -infinity to the value of its parent node whihch is the root node
The right child should be within the range of +infinity to the value of its parent node whihch is the root node
And go on comparing the current node's value within the range. If any node's value is not in the range then return False
class Solution:
def isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
return self.iterative(root)
# return self.recurse(root, float("inf"), float("-inf"))
def iterative(self, root):
if not root:
return True
level = [[root, -float("inf"), float("inf")]]
while level:
next_level = []
for element in level:
node, min_val, max_val = element
if min_val<node.val<max_val:
if node.left:
next_level.append([node.left, min_val, node.val])
if node.right:
next_level.append([node.right, node.val, max_val])
else:
return False
level = next_level
return True
def recurse(self, root, maxi, mini):
if root is None:
return True
if root.val < mini or root.val > maxi:
return False
return self.recurse(root.left, root.val-1, mini) and self.recurse(root.right, maxi, root.val+1)
Python implementation example. This example uses type annotations. However since Node class uses itself we need to include as a first line of the module:
from __future__ import annotations
Otherwise, you will get name 'Node' is not defined error. This example also uses dataclass as an example. To check if it's BST it uses recursion for checking left and right nodes values.
"""Checks if Binary Search Tree (BST) is balanced"""
from __future__ import annotations
import sys
from dataclasses import dataclass
MAX_KEY = sys.maxsize
MIN_KEY = -sys.maxsize - 1
#dataclass
class Node:
value: int
left: Node
right: Node
#property
def is_leaf(self) -> bool:
"""Check if node is a leaf"""
return not self.left and not self.right
def is_bst(node: Node, min_value: int, max_value: int) -> bool:
if node.value < min_value or max_value < node.value:
return False
elif node.is_leaf:
return True
return is_bst(node.left, min_value, node.value) and is_bst(
node.right, node.value, max_value
)
if __name__ == "__main__":
node5 = Node(5, None, None)
node25 = Node(25, None, None)
node40 = Node(40, None, None)
node10 = Node(10, None, None)
# balanced tree
node30 = Node(30, node25, node40)
root = Node(20, node10, node30)
print(is_bst(root, MIN_KEY, MAX_KEY))
# unbalanced tree
node30 = Node(30, node5, node40)
root = Node(20, node10, node30)
print(is_bst(root, MIN_KEY, MAX_KEY))
BST example
public bool IsBinarySearchTree(TreeNode root)
{
return IsValid(root, long.MinValue, long.MaxValue);
}
private static bool IsValid(TreeNode node, long min, long max)
{
if (node == null)
{
return true;
}
if (node.Value >= max || node.Value <= min)
{
return false;
}
return IsValid(node.Left, min, node.Value) && IsValid(node.Right, node.Value, max);
}
where TreeNode
public class TreeNode
{
public int Value;
public TreeNode Left;
public TreeNode Right;
public TreeNode(int value)
{
Value = value;
}
}
here's the detailed explanation https://codestandard.net/articles/validate-binary-search-tree/
Using inOrder Traversal..
First Adding the tree value to the array with inorder traversal.
Then iterate through the array which add a flag value true to split the elements after the root elements and before the root elements.
counter is added to check if the tree has elements with the same root value.
min and max is set to the range
var isValidBST = function(root)
{
if(!root) return false;
let current = root;
let data = [];
let flag = false;
let counter = 0;
function check(node){
if(node.left){
check(node.left);
}
data.push(node.val);
if(node.right){
check(node.right);
}
}
let min = Number.MIN_SAFE_INTEGER;
let max = root.val;
for(let i = 0; i < data.length; i++){
if(data[i] == root.val){
flag = true;
counter++;
}
if(flag){
if(data[i] < root.val || data[i] < max || counter > 1){
return false;
}
else{
max = data[i];
}
}
else{
if(data[i] > root.val || data[i] <= min|| counter > 1){
return false
}
else {
min = data[i]
}
}
}
return true;
};
We have to recursively ask each node if its left branch and right branch are valid binary search trees. The only thing each time we ask, we have to pass correct left and right boundaries:
class Solution:
def is_bst(self,root:TreeNode):
if not root:
return True
# left and right are boundaries
def dfs(node,left,right):
if not node:
return True
if not (node.val>left and node.val<right):
return False
# when we move right, we update the left, when we move left we update the right
return dfs(node.left,left,node.val) and dfs(node.right,node.val,right)
return dfs(root, float("-inf"), float("+inf"))
Here is the iterative solution without using extra space.
Node{
int value;
Node right, left
}
public boolean ValidateBST(Node root){
Node currNode = root;
Node prevNode = null;
Stack<Node> stack = new Stack<Node>();
while(true){
if(currNode != null){
stack.push(currNode);
currNode = currNode.left;
continue;
}
if(stack.empty()){
return;
}
currNode = stack.pop();
if(prevNode != null){
if(currNode.value < prevNode.value){
return false;
}
}
prevNode = currNode;
currNode = currNode.right;
}
}

Resources