当前位置:   article > 正文

JAVA程序设计:计算右侧小于当前元素的个数(LeetCode:315)_java实现 计算右侧小于当前元素的个数

java实现 计算右侧小于当前元素的个数

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

示例:

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

思路:我们先看另一道题:

给你一个数组,对于每个位置i,求出所有在i之前的比位置i上的数大的数

这不就是求逆序数嘛,这道题不是大同小异嘛,我们想一下求逆序数比较快速的方法,树状数组? 归并排序?线段树?

其实都是可以的,我们采用比较常用的归并排序吧。

对于三个数组的解释:

temp:存储元素的初始索引

indexes:存储元素排序后的最终索引

counter:每个位置上的答案

  1. class Solution {
  2. private int[] temp;
  3. private int[] counter;
  4. private int[] indexes;
  5. public List<Integer> countSmaller(int[] nums) {
  6. List<Integer> res=new ArrayList<>();
  7. int len=nums.length;
  8. if(len==0) return res;
  9. temp=new int[len];
  10. counter=new int[len];
  11. indexes=new int[len];
  12. for(int i=0;i<len;i++) indexes[i]=i;
  13. mergeAndCountSmaller(nums,0,len-1);
  14. for(int i=0;i<len;i++)
  15. res.add(counter[i]);
  16. return res;
  17. }
  18. private void mergeAndCountSmaller(int[] nums,int l,int r)
  19. {
  20. if(l==r) return;
  21. int mid=l+(r-l)/2;
  22. mergeAndCountSmaller(nums,l,mid);
  23. mergeAndCountSmaller(nums,mid+1,r);
  24. if(nums[indexes[mid]]>nums[indexes[mid+1]])
  25. mergeOfTwoSortedArrAndCountSmaller(nums,l,mid,r);
  26. }
  27. private void mergeOfTwoSortedArrAndCountSmaller(int[] nums,int l,int mid,int r)
  28. {
  29. for(int i=l;i<=r;i++)
  30. temp[i]=indexes[i];
  31. int i=l,j=mid+1;
  32. for(int k=l;k<=r;k++)
  33. {
  34. if(i>mid)
  35. {
  36. indexes[k]=temp[j];
  37. j++;
  38. }
  39. else if(j>r)
  40. {
  41. indexes[k]=temp[i];
  42. i++;
  43. counter[indexes[k]]+=r-mid;
  44. }
  45. else if(nums[temp[i]]<=nums[temp[j]])
  46. {
  47. indexes[k]=temp[i];
  48. i++;
  49. counter[indexes[k]]+=(j-mid-1);
  50. }
  51. else
  52. {
  53. indexes[k]=temp[j];
  54. j++;
  55. }
  56. }
  57. }
  58. }

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号