I had previously posted a question, Given an array, find out the next smaller element for each element now, i was trying to know , if there is any way to find out \"given an ar
It can be solved in O(n log n).
If in a BST you store the number of elements of the subtree rooted at that node when you search the node (reaching that from the root) you can count number of elements larger/smaller than that in the path:
int count_larger(node *T, int key, int current_larger){
if (*T == nil)
return -1;
if (T->key == key)
return current_larger + (T->right_child->size);
if (T->key > key)
return count_larger(T->left_child, key, current_larger + (T->right_child->size) + 1);
return count_larger(T->right_child, key, current_larger)
}
** for example if this is our tree and we're searching for key 3, count_larger will be called for:
-> (node 2, 3, 0)
--> (node 4, 3, 0)
---> (node 3, 3, 2)
and the final answer would be 2 as expected.
Another approach without using the tree.
Other than using BST, we can also solve this problem optimally by doing some modification in merge sort algorithm (in O(n*logn) time).
If you observe this problem more carefully, you can say that in the problem we need to count the number of inversions required for each element to make the array sorted in ascending order, right?
So this problem can be solved using Divide and Conquer paradigm. Here you need to maintain an auxiliary array for storing the count of inversions required (i.e. elements smaller than it on the right side of it).
Below is a python program:
def mergeList(arr, pos, res, start, mid, end):
temp = [0]*len(arr)
for i in range(start, end+1):
temp[i] = pos[i]
cur = start
leftcur = start
rightcur = mid + 1
while leftcur <= mid and rightcur <= end:
if arr[temp[leftcur]] <= arr[temp[rightcur]]:
pos[cur] = temp[leftcur]
res[pos[cur]] += rightcur - mid - 1
leftcur += 1
cur += 1
else:
pos[cur] = temp[rightcur]
cur += 1
rightcur += 1
while leftcur <= mid:
pos[cur] = temp[leftcur]
res[pos[cur]] += end - mid
cur += 1
leftcur += 1
while rightcur <= end:
pos[cur] = temp[rightcur]
cur += 1
rightcur += 1
def mergeSort(arr, pos, res, start, end):
if start < end:
mid = (start + end)/2
mergeSort(arr, pos, res, start, mid)
mergeSort(arr, pos, res, mid+1, end)
mergeList(arr, pos, res, start, mid, end)
def printResult(arr, res):
print
for i in range(0, len(arr)):
print arr[i], '->', res[i]
if __name__ == '__main__':
inp = input('enter elements separated by ,\n')
inp = list(inp)
res = [0]*len(inp)
pos = [ind for ind, v in enumerate(inp)]
mergeSort(inp, pos, res, 0, len(inp)-1)
printResult(inp, res)
Time : O(n*logn)
Space: O(n)
You can also use binary Index tree
int tree[1000005];
void update(int idx,int val)
{
while(idx<=1000000)
{
tree[idx]+=val;
idx+=(idx & -idx);
}
}
int sum(int idx)
{
int sm=0;
while(idx>0)
{
sm+=tree[idx];
idx-=(idx & -idx);
}
return sm;
}
int main()
{
int a[]={4,2,1,5,3};
int s=0,sz=6;
int b[10];
b[sz-1]=0;
for(int i=sz-2;i>=0;i--)
{
if(a[i]!=0)
{
update(a[i],1);
b[i]=sum(a[i]-1)+s;
}
else s++;
}
for(int i=0;i<sz-1;i++)
{
cout<<b[i]<<" ";
}
return 0;
}