You are given an integer array nums and you have to return a new counts array.The counts array has the property where counts[i]
is the number of smaller elements to the right of nums[i]
.
Example:
Given nums = [5, 2, 6, 1] To the right of 5 there are 2 smaller elements (2 and 1). To the right of 2 there is only 1 smaller element (1). To the right of 6 there is 1 smaller element (1). To the right of 1 there is 0 smaller element.
Return the array [2, 1, 1, 0]
.
Subscribe to see which companies asked this question
题目链接:https://leetcode.com/problems/count-of-smaller-numbers-after-self/
题目分析:其实就是求逆序数,可以用树状数组或归并排序实现,这里用的树状数组(感觉比归并好些的多。。。)
这是一开始写的,老老实实中规中矩的排序离散化,跑了26ms
public class Solution {
class Data implements Comparable {
int val, pos;
public Data(int val, int pos) {
this.val = val;
this.pos = pos;
}
@Override
public int compareTo(Object o) {
Data data = (Data) o;
if (this.val >= data.val) {
return 1;
}
else {
return -1;
}
}
}
public int lowbit(int x) {
return x & (-x);
}
public void add(int x, int len, int[] cnt) {
for (int i = x; i <= len; i += lowbit(i)) {
cnt[i] ++;
}
}
public int getCnt(int x, int[] cnt) {
int ans = 0;
for (int i = x; i > 0; i -= lowbit(i)) {
ans += cnt[i];
}
return ans;
}
public List<Integer> countSmaller(int[] nums) {
List<Integer> ans = new ArrayList<>();
int len = nums.length;
if (len == 0) {
return ans;
}
Data[] d = new Data[len];
int[] cnt = new int[len + 1];
int[] nums2 = new int[len + 1];
int[] rev = new int[len];
for (int i = 0; i < len; i ++) {
d[i] = new Data(nums[i], i + 1);
}
Arrays.sort(d);
nums2[d[0].pos] = 1;
int id = 1;
for(int i = 1; i < len; i ++) {
if (d[i].val == d[i - 1].val) {
nums2[d[i].pos] = id;
}
else {
nums2[d[i].pos] = ++ id;
}
}
int revCnt = 0;
for (int i = len; i >= 1; i --) {
add(nums2[i], len, cnt);
rev[revCnt ++] = getCnt(nums2[i] - 1, cnt);
}
for (int i = revCnt - 1; i >= 0; i --) {
ans.add(rev[i]);
}
return ans;
}
}
看了discuss里的一种离散化方法,瞬间8ms,不过那种离散化方法只适用于负数不太小,正数不太大的情况
public class Solution {
public int lowbit(int x) {
return x & (-x);
}
public void add(int x, int len, int[] cnt) {
for (int i = x; i <= len; i += lowbit(i)) {
cnt[i] ++;
}
}
public int getCnt(int x, int[] cnt) {
int ans = 0;
for (int i = x; i > 0; i -= lowbit(i)) {
ans += cnt[i];
}
return ans;
}
public List<Integer> countSmaller(int[] nums) {
List<Integer> ans = new ArrayList<>();
int len = nums.length;
if (len == 0) {
return ans;
}
int[] nums2 = new int[len + 1];
int[] rev = new int[len];
int mi = Integer.MAX_VALUE;
int ma = Integer.MIN_VALUE;
for (int i = 0; i < len; i ++) {
mi = Math.min(nums[i], mi);
}
for (int i = 1; i <= len; i ++) {
nums2[i] = nums[i - 1] - mi + 1;
ma = Math.max(ma, nums2[i]);
}
int[] cnt = new int[ma + 1];
int revCnt = 0;
for (int i = len; i >= 1; i --) {
add(nums2[i], ma, cnt);
rev[revCnt ++] = getCnt(nums2[i] - 1, cnt);
}
for (int i = revCnt - 1; i >= 0; i --) {
ans.add(rev[i]);
}
return ans;
}
}