方法一:
class Solution {
public List<Integer> countSmaller(int[] nums) {
List<Integer> res = new ArrayList<>(nums.length);
// 去重
Set<Integer> set = new HashSet<>();
for (int num : nums) {
set.add(num);
}
int n = set.size();
// 排序
int index = 0;
int[] uniqueNums = new int[n];
for (int num : set) {
uniqueNums[index] = num;
index++;
}
Arrays.sort(uniqueNums);
// 哈希表映射,key->实际值,value->排序后所处的数组下标
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < n; i++) {
map.put(uniqueNums[i], i);
}
int[] smallerArr = new int[nums.length];
int[] barrelArr = new int[n];
for (int i = nums.length - 1; i >= 0; i--) {
int barrelIdx = map.get(nums[i]);
barrelArr[barrelIdx] += 1;
int smallerSum = 0;
for (int j = 0; j < barrelIdx; j++) {
smallerSum += barrelArr[j];
}
smallerArr[i] = smallerSum;
}
for (int num : smallerArr) {
res.add(num);
}
return res;
}
}
方法二:
class Solution {
public List<Integer> countSmaller(int[] nums) {
int n = nums.length;
Pointer[] pointerArr = new Pointer[n];
for (int i = 0; i < n; i++) {
Pointer pointer = new Pointer();
pointer.val = nums[i];
pointer.smallerCount = 0;
pointerArr[i] = pointer;
}
mergeSort(pointerArr, 0, n - 1);
List<Integer> res = new ArrayList<>(n);
for (Pointer pointer : pointerArr) {
res.add(pointer.smallerCount);
}
return res;
}
public Pointer[] mergeSort(Pointer[] pointerArr, int left, int right) {
if (left > right) {
return null;
}
if (left == right) {
return new Pointer[] {pointerArr[left]};
}
int mid = (left + right) / 2;
int len = right - left + 1;
Pointer[] leftArr = mergeSort(pointerArr, left, mid);
Pointer[] rightArr = mergeSort(pointerArr, mid + 1, right);
Pointer[] mergeArr = new Pointer[len];
int leftIdx = 0, rightIdx = 0;
while (leftIdx < leftArr.length || rightIdx < rightArr.length) {
// 左区间已遍历完,右区间数组后续值都比左区间大
if (leftIdx >= leftArr.length) {
mergeArr[leftIdx + rightIdx] = rightArr[rightIdx++];
continue;
}
// 找到左区间比右区间哪些数更大
while (rightIdx < rightArr.length && leftArr[leftIdx].val > rightArr[rightIdx].val) {
mergeArr[leftIdx + rightIdx] = rightArr[rightIdx++];
}
leftArr[leftIdx].smallerCount += rightIdx;
mergeArr[leftIdx + rightIdx] = leftArr[leftIdx++];
}
return mergeArr;
}
}
class Pointer {
public int val;
public int smallerCount;
}