Count smaller elements on right side
Write a function to count number of smaller elements on right of each element in an array. Given an unsorted array arr[] of distinct integers, construct another array countSmaller[] such that countSmaller[i] contains count of smaller elements on right side of each element arr[i] in array.
Examples:
Input: arr[] = {12, 1, 2, 3, 0, 11, 1}
Output: countSmaller[] = {6, 1, 2, 2, 0, 1, 0}
(Corner Cases)
Input: arr[] = {5, 4, 3, 2, 1}
Output: countSmaller[] = {4, 3, 2, 1, 0}
Input: arr[] = {1, 2, 3, 4, 5}
Output: countSmaller[] = {0, 0, 0, 0, 0}
Method 1 (Simple)
Use two loops. The outer loop picks all elements from left to right. The inner loop iterates through all the elements on right side of the picked element and updates countSmaller[].
void constructLowerArray (int *arr[], int *low, int n)
{
int i, j;
// initialize all the counts in countSmaller array as 0
for (i = 0; i < n; i++)
countSmaller[i] = 0;
for (i = 0; i < n; i++)
{
for (j = i+1; j < n; j++)
{
if (arr[j] < arr[i])
countSmaller[i]++;
}
}
}
/* Utility function that prints out an array on a line */
void printArray(int arr[], int size)
{
int i;
for (i=0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
// Driver program to test above functions
int main()
{
int arr[] = {12, 10, 5, 4, 2, 20, 6, 1, 0, 2};
int n = sizeof(arr)/sizeof(arr[0]);
int *low = (int *)malloc(sizeof(int)*n);
constructLowerArray(arr, low, n);
printArray(low, n);
return 0;
}
Time Complexity: O(n^2)
Auxiliary Space: O(1)
Method 2 (Use BST)
A Self Balancing Binary Search Tree (AVL, Red Black,.. etc) can be used to get the solution in O(nLogn) time complexity. A Self Balancing Binary Search Tree(BST) can be augmented to contain count of smaller values in every node. We can store this info by storing count of nodes in left subtree. The BST insert function must be augmented in such a way that it increments the count for those ancestors for which, the node being inserted is in left subtree. The BST delete function must also be augmented in such a way that decrements the count for those ancestors for which, the node being deleted is in left subtree. Both of these operations can still be done in O(Logn) complexity.
Following is the algorithm that constructs countSmaller[] using the above Augmented Self Balancing BST.
1) Traverse the array from left to right and construct a BST such that every node of BST also contains count of nodes in left subtree. O(nLogn)
2) Traverse the array again from left to right and do following for every array element arr[i] .
…..a) Search the element arr[i] in BST, get the count of nodes in left subtree and store it in countSmaller[i]
…..b) Delete the node (which contains arr[i]) from BST
The step 2 b) is necessary to make sure that the smaller nodes on left side (in array) are deleted before we consider count for a node.
Time Complexity: O(nLogn)
Auxiliary Space: O(n)
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Tweet
can anyone explain the second method with example?
In the 1st example for Method 2.
12 -> 2 -> 1
makes a rearrangement. Before rearrangement the left subtree count of 12 is 2. So after rearrangement will it be 0 ??
#include
void rightsmaller(int a[])
{
int count[20]={0},i=0,j=0;
count[0]=0;
for( i=0;i0)
{
for(j=0;j<i;j++)
{
if(a[j]<a[i])
{
count[i]++;
}
}
}
}
// display the array count
for(i=0;i<8;i++)
printf("%d ",count[i]);
}
int main()
{
int array[]={2,1,3,4,6,1,9,8};
rightsmaller(array);
}
@Rahul Sharm: Could you please post the code again within the sourcecode tags
we can even do this with a simple recursive method right
public int numSmaller(int[] elements, int position){ if(position == (elements.length-1)){ return 0; } return numSmaller(int[] elements, position+1) + isMin(int[] elements, position); } public int isMin(int elements[], int presentPosition){ if(elements[presentPosition] > elements[presentPosition+1]){ return 1; } return 0; }Time Complexity will be O(n)
Your second algorithm is wrong as per the question.
Questions says smaller elements to the right, not all smaller elements.
@Sanju: Please take a closer look at the algorithm. After finding smaller elements for an elemenet, we delete the element from tree. By Deletion, we make sure that this node is not considered when we are processing elements to its right.
can someone explain the approach with an example ?
Second case source code
pass the following parameters
arr=input arr;
min=array where the value to be stored
n=size of array arr
typedef struct node { int data; node *left,*right; int small; }; void fun(int arr[],int mins[],int n) { node *root=NULL; for(int i=n-1;i>=0;i--) { int num=arr[i]; if(root==NULL) //to check if root tree //exist or not,executed only once { root=new node; root->data=num; root->left=root->right=NULL; root->small=0; mins[i]=0; } else { node *mover=root; int count=0; while(1) { if((mover->data)<num) { //if the value is bigger at the current node into count count++; //add the number of nodes which are smaller then current node count+=mover->small; if(mover->right!=NULL) mover=mover->right; else break; } else { mover->small=mover->small+1; //add one more node in the number of "small nodes" if(mover->left!=NULL) mover=mover->left; else break; } } node *x= new node; x->data=arr[i]; x->left=x->right=NULL; x->small=0; if((mover->data)<num) mover->right=x; else mover->left=x; mins[i]=count; } } }i guess your tree isn't balance .......... so at the worst case scenario complexity will be again O(0logN).......... however it can be improved using AVL tree .... i had tried and its working fine but code is too lengthy ..............
i mean to say complexity will be O(n2) not O(nlogn)
yup..for skewed trees it would be O(n^2)
you can first sort the array which can be done in O(nlogn) and after that fill the countsmaller array with the value=n-index of element in count smaller array.
one thing that need to be kept in mind that if the array is containing the duplicate elements that an additional check is also required to account that.but that also can be done in O(n).
so overall complexity would be O(nlogn).
Looks like you didn't get the question. It is not about all smaller elements, but elements only on the right side.
A good example that shows use of self balancing BSTs.
Can somebody please share the code for method 2?