当前位置: 首页 > news >正文

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

题目

. - 力扣(LeetCode)

这道题是2022-5,华为软件岗暑期实习机考第一题。

思路 

这道题的核心思路是借助归并排序,在归并排序过程计算的同时,加入一点步骤来算出我们的结果,所以需完全理解归并排序的前提来理解。

众所周知,归并排序时,我们递归排序完左右区间,需要对两个区间进行合并有序数组,我们就是在合并有序数组时加入我们的特殊步骤,来到合并有序数组时:

现在需要将上图左右区间两个降序的数组,合并为一个有序数组,正常归并排序思路每一数组定义一个指针,取大的尾插进入新数组,现在来到我们的尾插过程中:

因为是降序,所以每个指针遍历过的元素肯定是对应区间内较大的元素,尾插过程中就可能会出现如下两种情况:

1.nums[cur1] <= nums[cur2],这时只需将较大的nums[cur2]尾插进入新数组即可。

2.nums[cur1] > nums[cur2],这时,不难发现由于数组是降序的,所以cur2后面的元素肯定都小于cur2指向的元素,又nums[cur1] > nums[cur2],所以cur2后面的元素都是比cur1指向的元素小,此时就可以将ret数组对应的cur1的下标位置的元素+=上cur2后面元素的个数。

注意:由于归并排序会改变元素的位置,我们需要创建一个index数组来记录原始下标,跟随原数组一起排序移动,才能方便ret数组的答案记录。

代码:

class Solution {vector<int> ret;//答案数组vector<int> index;//记录数组元素的原始下标int tmpNums[500010];//临时nums数组,归并排序中帮助排序使用int tmpIndex[500010];//临时index数组,让index中的元素跟随nums中的元素移动,方便ret记录
public:vector<int> countSmaller(vector<int>& nums) {int n = nums.size();ret.resize(n);index.resize(n);//初始化index数组for(int i = 0;i<n;i++)index[i] = i;mergesort(nums,0,n-1);return ret;}void mergesort(vector<int>& nums,int left,int right){   //递归结束条件if(left >= right) return;//取中划分区间int mid = (right + left) >> 1;//递归左右区间mergesort(nums,left,mid);mergesort(nums,mid + 1,right);//开始合并两个有序区间int cur1 = left,cur2 = mid + 1, i = 0;while(cur1 <= mid&&cur2 <= right){if(nums[cur1] <= nums[cur2]){tmpNums[i] = nums[cur2];tmpIndex[i++] = index[cur2++];}else{   //记录答案ret[index[cur1]] += right - cur2 + 1;//重点tmpNums[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}}//归并排序正常流程,没走完的尾插while(cur1 <= mid){tmpNums[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}while(cur2 <= right){tmpNums[i] = nums[cur2];tmpIndex[i++] = index[cur2++];}//将临时数组的元素搬回原数组,完成排序for(int j = left;j<=right;j++){nums[j] = tmpNums[j - left];index[j] = tmpIndex[j - left];}}
};

 

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【C++】—— 类与对象(二)
  • [Git][认识Git]详细讲解
  • 【启明智显分享】适用于多功能养生壶、茶吧机的2.8寸触摸彩屏解决方案
  • uni-app封装组件实现下方滑动弹出模态框
  • NeRF学习——复现训练中的问题记录
  • 【全国大学生电子设计竞赛】2022年E题
  • TCP Analysis Flags 之 TCP Window Full
  • 解决 Vue 页面中地址栏参数变更不刷新的问题
  • react防抖和节流hooks封装
  • Hystrix 线程池策略时使用ThreadLocal
  • 【LeetCode】219.存在重复元素II
  • STM32卡死、跑飞如何调试确定问题
  • CMD运行指令
  • 鸿蒙系统开发【ASN.1密文转换】安全
  • 线程池工具类 Executors源代码详解
  • 【RocksDB】TransactionDB源码分析
  • 230. Kth Smallest Element in a BST
  • AngularJS指令开发(1)——参数详解
  • conda常用的命令
  • Just for fun——迅速写完快速排序
  • Linux链接文件
  • Python连接Oracle
  • React 快速上手 - 07 前端路由 react-router
  • session共享问题解决方案
  • Vue UI框架库开发介绍
  • Vue官网教程学习过程中值得记录的一些事情
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 判断客户端类型,Android,iOS,PC
  • 区块链分支循环
  • 设计模式(12)迭代器模式(讲解+应用)
  • 设计模式走一遍---观察者模式
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 运行时添加log4j2的appender
  • 《天龙八部3D》Unity技术方案揭秘
  • Python 之网络式编程
  • 阿里云ACE认证学习知识点梳理
  • ​如何防止网络攻击?
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #《AI中文版》V3 第 1 章 概述
  • #include
  • #Linux(make工具和makefile文件以及makefile语法)
  • $GOPATH/go.mod exists but should not goland
  • $LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (2024,RWKV-5/6,RNN,矩阵值注意力状态,数据依赖线性插值,LoRA,多语言分词器)Eagle 和 Finch
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (k8s)Kubernetes本地存储接入
  • (备忘)Java Map 遍历
  • (编译到47%失败)to be deleted
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (每日一问)操作系统:常见的 Linux 指令详解
  • (十八)SpringBoot之发送QQ邮件
  • (实战)静默dbca安装创建数据库 --参数说明+举例