当前位置:   article > 正文

计算右侧小于当前元素的个数_统计数组中右边比小的

统计数组中右边比小的


这道题利用归并排序,几乎和归并排序一样,不同的地方在于将两个有序数组合并的地方需要添加几行代码。

所以我们要找出规律,举例如下:

在归并两排序数组时,当需要将前一个数组元素的指针 i 指向的元素插入时,它对应的 count[i] ,就是后一个数组的指针j 的值

  1. //count: 0 0 0 0 0 0 0 0
  2. //nums: -7 1 5 9 -2 1 3 5
  3. // i j=3

比如此时到了5这个数,它的count就是3 = j,比5小的数的个数就+3

因为在左边数组sub_vec1,已经有序了,所以比5小的数,且在5右边的,也就只能从sub_vec2中找,sub_vec[2],也就是5,和sub_vec[j]比较时,比5小的话,j就会后移,j++,所以就有了上面那条规律。

  1. class Solution {
  2. public:
  3. vector<int> countSmaller(vector<int>& nums) {
  4. vector<int>count;//保存结果
  5. vector<pair<int,int> > num;//关联每个数和它的序号
  6. for(int i =0;i<nums.size();++i)
  7. {
  8. count.push_back(0);
  9. num.push_back(make_pair(nums[i],i));//保存每个数和它在原数组中的序号,以免在排序过程中打乱顺序
  10. }
  11. merge_sort(num,count);
  12. return count;
  13. }
  14. //归并排序
  15. void merge_sort(vector<pair<int,int> >& vec, vector<int>& count)
  16. {
  17. if(vec.size()<2)
  18. return;
  19. int mid = vec.size()/2;
  20. vector<pair<int,int> > sub_vec1;
  21. vector<pair<int,int> > sub_vec2;
  22. for(int i =0;i<mid;++i)
  23. sub_vec1.push_back(vec[i]);
  24. for(int i =mid;i< vec.size();++i)
  25. sub_vec2.push_back(vec[i]);
  26. merge_sort(sub_vec1,count);
  27. merge_sort(sub_vec2,count);
  28. vec.clear();
  29. merge(sub_vec1,sub_vec2,vec,count);
  30. }
  31. //合并两数组
  32. void merge(vector<pair<int,int> >& sub_vec1,vector<pair<int,int> >& sub_vec2, vector<pair<int,int> >& vec, vector<int>& count)
  33. {
  34. int i =0;
  35. int j =0;
  36. while(i < sub_vec1.size() && j < sub_vec2.size())
  37. {
  38. if(sub_vec1[i].first <= sub_vec2[j].first )
  39. {
  40. vec.push_back(sub_vec1[i]);
  41. count[sub_vec1[i].second] += j;//这句话和下面注释的地方就是这道题和归并排序的主要不同之处
  42. i++;
  43. }else{
  44. vec.push_back(sub_vec2[j]);
  45. j++;
  46. }
  47. }
  48. for(;i<sub_vec1.size();++i)
  49. {
  50. vec.push_back(sub_vec1[i]);
  51. count[sub_vec1[i].second] += j;// -。-
  52. }
  53. for(;j<sub_vec2.size();++j)
  54. {
  55. vec.push_back(sub_vec2[j]);
  56. }
  57. }
  58. };

方法二:用二叉查找树

将Nums逆置,count[i]就变成了nums[0]...nums[i-1]中有多少个比nums【i】小的数

将元素按照逆置后的顺序插入到二叉查找树,在插入结点时,当待插入结点值小于等于当前结点时,node->count++

大于当前结点时,count_small+=node->count+1;

  1. struct BSTNode{
  2. int val;
  3. int count;//二叉树左子树中节点的个数
  4. BSTNode* left;
  5. BSTNode* right;
  6. BSTNode(int x):val(x),count(0),left(NULL),right(NULL){}
  7. };
  8. class Solution {
  9. public:
  10. void BST_insert(BSTNode* node,BSTNode* insert_node,int& count_small)//count_small,二叉排序树中比插入节点值小的结点个数
  11. {
  12. if(insert_node->val <= node->val)
  13. {
  14. node->count++;
  15. if(node->left)
  16. BST_insert(node->left,insert_node,count_small);
  17. else
  18. node->left = insert_node;
  19. }else{
  20. count_small = count_small + node->count + 1;
  21. if(node->right)
  22. BST_insert(node->right,insert_node,count_small);
  23. else
  24. node->right = insert_node;
  25. }
  26. }
  27. vector<int> countSmaller(vector<int>& nums) {
  28. vector<int> res;//最后的结果
  29. vector<BSTNode*> node_vec;//创建的二叉查找树的结点池
  30. vector<int> count;//count_small数组
  31. for(int i = nums.size() - 1;i>=0;--i)
  32. node_vec.push_back(new BSTNode(nums[i]));
  33. count.push_back(0);//第一个结点的count_small为0
  34. for(int i = 1;i<node_vec.size();++i)
  35. {
  36. int count_small = 0;
  37. BST_insert(node_vec[0],node_vec[i],count_small);
  38. count.push_back(count_small);
  39. }
  40. for(int i =node_vec.size()-1;i>=0;--i)
  41. res.push_back(count[i]);//将结果顺序调换为原来的顺序
  42. return res;
  43. }
  44. };

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/87151
推荐阅读
相关标签
  

闽ICP备14008679号