Reputation: 325
This is an interview Question.
A binary search tree is given and the values of two nodes have been swapped. The question is how to find both the nodes and the swapped values in a single traversal of the tree?
i have tried to solve this using below code but i am not able to stop the recursion so i am getting segmentation fault. help me how to stop recursion.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <stdlib.h>
/* A binary tree node has data, pointer to left child
and a pointer to right child */
struct node
{
int data;
struct node* left;
struct node* right;
};
/* Helper function that allocates a new node with the
given data and NULL left and right pointers. */
struct node* newNode(int data)
{
struct node* node = (struct node*)
malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
void modifiedInorder(struct node *root, struct node **nextNode)
{
static int nextdata=INT_MAX;
if(root)
{
modifiedInorder(root->right, nextNode);
if(root->data > nextdata)
return;
*nextNode = root;
nextdata = root->data;
modifiedInorder(root->left, nextNode);
}
}
void inorder(struct node *root, struct node *copyroot, struct node **prevNode)
{
static int prevdata = INT_MIN;
if(root)
{
inorder(root->left, copyroot, prevNode);
if(root->data < prevdata)
{
struct node *nextNode = NULL;
modifiedInorder(copyroot, &nextNode);
int data = nextNode->data;
nextNode->data = (*prevNode)->data;
(*prevNode)->data = data;
return;
}
*prevNode = root;
prevdata = root->data;
inorder(root->right, copyroot, prevNode);
}
}
/* Given a binary tree, print its nodes in inorder*/
void printInorder(struct node* node)
{
if (node == NULL)
return;
/* first recur on left child */
printInorder(node->left);
/* then print the data of node */
printf("%d ", node->data);
/* now recur on right child */
printInorder(node->right);
}
int main()
{
/* 4
/ \
2 3
/ \
1 5
*/
struct node *root = newNode(1); // newNode will return a node.
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
printf("Inorder Traversal of the original tree\n ");
printInorder(root);
struct node *prevNode=NULL;
inorder(root, root, &prevNode);
printf("\nInorder Traversal of the fixed tree \n");
printInorder(root);
return 0;
}
Upvotes: 3
Views: 4718
Reputation: 11
We can solve this in O(n) time and with a single traversal of the given BST. Since inorder traversal of BST is always a sorted array, the problem can be reduced to a problem where two elements of a sorted array are swapped. There are two cases that we need to handle:
6
/ \
10 2
/ \ / \
1 3 7 12
1. The swapped nodes are not adjacent in the inorder traversal of the BST.
For example, Nodes 10 and 2 are swapped in {1 10 3 6 7 2 12}. The inorder traversal of the given tree is 1 10 3 6 7 2 12
If we observe carefully, during inorder traversal, we find node 3 is smaller than the previous visited node 10. Here save the context of node 10 (previous node). Again, we find that node 2 is smaller than the previous node 7. This time, we save the context of node 2 ( current node ). Finally swap the two node’s values.
2. The swapped nodes are adjacent in the inorder traversal of BST.
6
/ \
10 8
/ \ / \
1 3 7 12
For example, Nodes 10 and 2 are swapped in {1 10 3 6 7 8 12}. The inorder traversal of the given tree is 1 10 3 6 7 8 12 Unlike case #1, here only one point exists where a node value is smaller than previous node value. e.g. node 10 is smaller than node 36.
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void recoverTreeUtil(TreeNode *root, TreeNode **first, TreeNode **middle, TreeNode **last, TreeNode **prev) {
if (root) {
recoverTreeUtil(root->left, first, middle, last, prev);
if (*prev && (*prev)->val > root->val) {
if (!(*first)) {
*first = *prev;
*middle = root;
} else *last = root;
}
*prev = root;
recoverTreeUtil(root->right, first, middle, last, prev);
}
}
void recoverTree(TreeNode* root) {
TreeNode *first, *middle, *last, *prev;
first = middle = last = prev = nullptr;
recoverTreeUtil(root, &first, &middle, &last, &prev);
if (first && last) swap(first->val, last->val);
else if (first && middle) swap(first->val, middle->val);
}
};
Upvotes: 1
Reputation: 812
My C++ Solution:
struct node *correctBST( struct node* root )
{
//add code here.
if(!root)return root;
struct node* r = root;
stack<struct node*>st;
// cout<<"1"<<endl;
struct node* first = NULL;
struct node* middle = NULL;
struct node* last = NULL;
struct node* prev = NULL;
while(root || !st.empty()){
while(root){
st.push(root);
root = root->left;
}
root = st.top();
st.pop();
if(prev && prev->data > root->data){
if(!first){
first = prev;
middle = root;
}
else{
last = root;
}
}
prev = root;
root = root->right;
}
if(first && last){
swap(first->data,last->data);
}
else{
swap(first->data,middle->data);
}
return r;
}
Upvotes: -1
Reputation:
I found another solution to this questions on Geeksforgeeks.com ..............guys u can look into this thread for more explanation of below code http://www.geeksforgeeks.org/archives/23616
// Two nodes in the BST's swapped, correct the BST.
#include <stdio.h>
#include <stdlib.h>
/* A binary tree node has data, pointer to left child
and a pointer to right child */
struct node
{
int data;
struct node *left, *right;
};
// A utility function to swap two integers
void swap( int* a, int* b )
{
int t = *a;
*a = *b;
*b = t;
}
/* Helper function that allocates a new node with the
given data and NULL left and right pointers. */
struct node* newNode(int data)
{
struct node* node = (struct node *)malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
// This function does inorder traversal to find out the two swapped nodes.
// It sets three pointers, first, middle and last. If the swapped nodes are
// adjacent to each other, then first and middle contain the resultant nodes
// Else, first and last contain the resultant nodes
void correctBSTUtil( struct node* root, struct node** first,
struct node** middle, struct node** last,
struct node** prev )
{
if( root )
{
// Recur for the left subtree
correctBSTUtil( root->left, first, middle, last, prev );
// If this node is smaller than the previous node, it's violating
// the BST rule.
if (*prev && root->data < (*prev)->data)
{
// If this is first violation, mark these two nodes as
// 'first' and 'middle'
if ( !*first )
{
*first = *prev;
*middle = root;
}
// If this is second violation, mark this node as last
else
*last = root;
}
// Mark this node as previous
*prev = root;
// Recur for the right subtree
correctBSTUtil( root->right, first, middle, last, prev );
}
}
// A function to fix a given BST where two nodes are swapped. This
// function uses correctBSTUtil() to find out two nodes and swaps the
// nodes to fix the BST
void correctBST( struct node* root )
{
// Initialize pointers needed for correctBSTUtil()
struct node *first, *middle, *last, *prev;
first = middle = last = prev = NULL;
// Set the poiters to find out two nodes
correctBSTUtil( root, &first, &middle, &last, &prev );
// Fix (or correct) the tree
if( first && last )
swap( &(first->data), &(last->data) );
else if( first && middle ) // Adjacent nodes swapped
swap( &(first->data), &(middle->data) );
// else nodes have not been swapped, passed tree is really BST.
}
/* A utility function to print Inoder traversal */
void printInorder(struct node* node)
{
if (node == NULL)
return;
printInorder(node->left);
printf("%d ", node->data);
printInorder(node->right);
}
/* Driver program to test above functions*/
int main()
{
/* 6
/ \
10 2
/ \ / \
1 3 7 12
10 and 2 are swapped
*/
struct node *root = newNode(6);
root->left = newNode(10);
root->right = newNode(2);
root->left->left = newNode(1);
root->left->right = newNode(3);
root->right->right = newNode(12);
root->right->left = newNode(7);
printf("Inorder Traversal of the original tree \n");
printInorder(root);
correctBST(root);
printf("\nInorder Traversal of the fixed tree \n");
printInorder(root);
return 0;
}
Output:
Inorder Traversal of the original tree
1 10 3 6 7 2 12
Inorder Traversal of the fixed tree
1 2 3 6 7 10 12
Time Complexity: O(n)
For more test cases please refer to this link http://ideone.com/uNlPx
Upvotes: 0
Reputation: 5535
The following function validates if a tree is BST or not by recursively iterating both left and right subtrees while tightening the bounds.
I believe it can be modified to achieve the above task by
EDIT: We would need to distinguish between recursive function returning true vs pointer to node which is swapped
This assumes that there are only two such values as mentioned in the problem definition
bool validate_bst(tnode *temp, int min, int max)
{
if(temp == NULL)
return true;
if(temp->data > min && temp->data < max)
{
if( validate_bst(temp->left, min, temp->data) &&
validate_bst(temp->right, temp->data, max) )
return true;
}
return false;
}
The main would call above api like this
validate_bst(root, -1, 100); // Basically we pass -1 as min and 100 as max in
// this instance
Upvotes: 2
Reputation:
Walk to the tree using inorder traversal. By using that you will get all the elements sorted and the one element that will be greater than the surrounding elements is swapped.
For example consider this below binary tree
_ 20 _
/ \
15 30
/ \ / \
10 17 25 33
/ | / \ / \ | \
9 16 12 18 22 26 31 34
First, we linearize this into an array and we get
9 10 16 15 12 17 18 20 22 25 26 30 31 33 34
Now you can notice that 16 is greater than its surrounding elements and that 12 is less than them. This immediately tells us that 12 and 16 were swapped.
Upvotes: 7