题目

给你一个整数数组 nums ,按要求返回一个新数组 counts 。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。

示例 1:

输入:nums = [5,2,6,1]
输出:[2,1,1,0]
解释:
5 的右侧有 2 个更小的元素 (2 和 1)
2 的右侧仅有 1 个更小的元素 (1)
6 的右侧有 1 个更小的元素 (1)
1 的右侧有 0 个更小的元素

示例 2:

输入:nums = [-1]
输出:[0]

示例 3:

输入:nums = [-1,-1]
输出:[0,0]

提示:

1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-of-smaller-numbers-after-self
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

想学习树状数组,来回顾一下这个题,这个题可以当做树状数组的入门例题。

代码

树状数组

  1. class Solution {
  2. public List<Integer> countSmaller(int[] nums) {
  3. // 首先离散化,可以节省树状数组空间
  4. // 下面一行代码对numns去重并排序
  5. // [6, 8, 5, 7, 5, 7, 1] 会得到 [1, 5, 6, 7, 8]
  6. int[] arr = Arrays.stream(nums).distinct().sorted().toArray();
  7. // 然后使用哈希表记录每个数的rank,key为arr元素,value为位次,越小的数位次越靠前
  8. // 1, 5, 6, 7, 8 位次分别是 1,2,3,4,5
  9. Map<Integer, Integer> map = new HashMap<>();
  10. int n = arr.length;
  11. for (int i = 0; i < n; i++) {
  12. map.put(arr[i], i + 1);
  13. }
  14. List<Integer> ans = new ArrayList<>();
  15. FenwickTree fenwickTree = new FenwickTree(n);
  16. // 因为看右侧有多少数比自己小,因此倒着遍历
  17. for (int i = nums.length - 1; i >= 0; i--) {
  18. int num = nums[i];
  19. int rank = map.get(num);
  20. // 下面两行可以交换
  21. // 当前数排名为rank,那么查询tree数组中rank下标前面(不包括rank)有多少数,即查询rank-1的前缀和
  22. ans.add(fenwickTree.query(rank - 1));
  23. // 在tree中将rank加1
  24. fenwickTree.update(rank, 1);
  25. }
  26. Collections.reverse(ans);
  27. return ans;
  28. }
  29. }
  30. public class FenwickTree {
  31. private int[] tree;
  32. private int len;
  33. public FenwickTree(int n) {
  34. this.len = n;
  35. tree = new int[n + 1];
  36. }
  37. public FenwickTree(int[] nums) {
  38. this.len = nums.length + 1;
  39. tree = new int[this.len + 1];
  40. for (int i = 1; i <= len; i++) {
  41. update(i, nums[i]);
  42. }
  43. }
  44. public void update(int i, int delta) {
  45. while (i <= len) {
  46. tree[i] += delta;
  47. i += lowbit(i);
  48. }
  49. }
  50. public int query(int i) {
  51. int sum = 0;
  52. while (i > 0) {
  53. sum += tree[i];
  54. i -= lowbit(i);
  55. }
  56. return sum;
  57. }
  58. public static int lowbit(int x) {
  59. return x & (-x);
  60. }
  61. }