package com.interview.array; import java.util.ArrayList; import java.util.List; /** * Date 03/01/2016 * @author Tushar Roy * * Count number of smaller elements on right side of an array for every element. * * Time complexity is O(nlogn) * Space complexity is O(n) * * https://leetcode.com/problems/count-of-smaller-numbers-after-self/ */ public class CountSmallerOnRight { static class NumberIndex { int val; int index; NumberIndex(int val, int index) { this.val = val; this.index = index; } } public List<Integer> countSmaller(int[] nums) { if (nums.length == 0) { return new ArrayList<>(); } NumberIndex[] input = new NumberIndex[nums.length]; for (int i = 0; i < nums.length; i++) { input[i] = new NumberIndex(nums[i], i); } int result[] = new int[nums.length]; mergeUtil(input, result, 0, input.length - 1); List<Integer> r = new ArrayList<>(); for (int s : result) { r.add(s); } return r; } private void mergeUtil(NumberIndex[] nums, int[] result, int low, int high) { if (low == high) { return; } int mid = (low + high)/2; mergeUtil(nums, result, low, mid); mergeUtil(nums, result, mid + 1, high); int i = low; int j = mid + 1; NumberIndex[] t = new NumberIndex[high - low + 1]; int k = 0; int tempResult[] = new int[high - low + 1]; while (i <= mid && j <= high) { if (nums[i].val <= nums[j].val) { tempResult[nums[i].index - low] = j - mid - 1; t[k++] = nums[i++]; } else { tempResult[nums[i].index - low] = j - mid; t[k++] = nums[j++]; } } int i1= i; while (i1 <= mid) { tempResult[nums[i1].index - low] = j - mid - 1; t[k++] = nums[i1++]; } while (j <= high) { t[k++] = nums[j++]; } k = 0; for (i = low; i <= high; i++) { nums[i] = t[k]; result[i] += tempResult[k++]; } } public static void main(String args[]) { CountSmallerOnRight csr = new CountSmallerOnRight(); int nums[] = {5, 2, 6, 1, 0, 3}; List<Integer> result = csr.countSmaller(nums); result.forEach(r -> System.out.print(r + " ")); } }