题目描述:

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。

输入一个数组,求出这个数组中的逆序对的总数。

示例 1:

输入: [7,5,6,4]
输出: 5

限制:

0 <= 数组长度 <= 50000

分析:

本题的暴力方法显然容易想到,但是会报超时,难度等级 hard 显示 考察的是使用

时间O(log n*logn)空间 O(n)的解法。可以使用 「归并排序」 和 「线段树」 两种方法。

利用「归并排序」和「线段树」计算逆序对都是非常经典的做法。这里我们暂且只考虑

利用「归并排序」计算逆序对。

思想是「分治算法」,所有的「逆序对」来源于 3 个部分:

  • 左边区间的逆序对;
  • 右边区间的逆序对;
  • 横跨两个区间的逆序对。

计算左边区间的逆序对和右边区间的逆序对都是规模更小的子问题,直接交给递归去完成。

重点是分析计算横跨两个区间的逆序对。计算横跨两个区间的逆序对时,上面的两个子问题都已经让递归函数完成了,

此时,左边区间的逆序对和右边区间的逆序对都已经计算出来了,且左边区间和右边区间都已经有序了。

计算横跨两个区间的逆序对 具体步骤如下:

1.  将给定区间 nums[l,r] 分成 左区间  nums[l , mid] ,右区间 nums[mid + 1,r] ,使用双指针同步遍历左右区间;

2.  如果左边区间当前的元素num[i] 小于等于 右边区间当前的元素nums [j],因为nums[i] 小于等于右边区间

所有的元素nums[j,r],nums[i]  不会和右区间内的元素nums[j,r] 构成逆序对。直接将nums[i] 放入归并排序的辅助空间。

3.   如果左边区间当前的元素num[i] 大于 右边区间当前的元素nums [j],那左边区间元素num[i,mid] ,一共 mid - i + 1 个都比

右边区间当前的元素nums[j]大,且都在右边区间当前的元素前面,和右边区间当前元素 构成  mid - i + 1  个逆序对。

加到总的逆序对数上,再将右边区间当前的元素nums [j] 放到缓冲区。

3.  将左(右)区间比较多出来的元素直接加到辅助空间中.

4. 将辅助空间中排序好的元素 再重新放回nums[l,r];

5. 函数返回当前区间计算得到的总的逆序对数。

代码如下:

 1 class Solution {
2 public:
3 vector<int> tmp;//归并排序的辅助数组
4
5 int reversePairs(vector<int>& nums) {
6 tmp.assign(nums.size(),0);
7 return merge_sort(nums,0,nums.size() - 1);
8 }
9
10 long long int merge_sort(vector<int>& nums,int l,int r)
11 {
12 if(l >= r)//归并排序递归出口
13 {
14 return 0;
15 }
16 int mid = l + (r - l)/2;//将区间一分为二
17 long long ans = merge_sort(nums,l,mid) + merge_sort(nums,mid + 1,r);//递归地求左右子数组的逆序对个数和
18 int k = 0,i = l,j = mid + 1;//计算 横跨左右区间的逆序对
19 while(i <= mid && j <= r)
20 {
21 if(nums[i] <= nums[j])
22 {
23 tmp[k++] = nums[i++];
24 }
25 else
26 { //执行上述递归之后,左右子数组都已经排好序
27 //nums[i:mid] 都比nums[j] 大,都和num[j] 构成逆序对
28 ans += (mid - i + 1);
29 tmp[k++] = nums[j++];
30 }
31 }
32 while(i <= mid) tmp[k++] = nums[i++];
33 while(j <= r) tmp[k++] = nums[j++];
34 //将排序好的元素移回原数组,放在原来的区间上
35 for(i = l,j = 0;i <= r; )
36 {
37 nums[i++] = tmp[j++];
38 }
39 return ans;
40 }
41 };

微软面试题:剑指 Offer 51. 数组中的逆序对 Hard 出现次数:3的更多相关文章

  1. 剑指 Offer 51. 数组中的逆序对 + 归并排序 + 树状数组

    剑指 Offer 51. 数组中的逆序对 Offer_51 题目描述 方法一:暴力法(双层循环,超时) package com.walegarrett.offer; /** * @Author Wal ...

  2. 【Java】 剑指offer(51)数组中的逆序对

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成 ...

  3. 【剑指offer】数组中的逆序对

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/mmc_maodun/article/details/27520535 转载请注明出处:http:// ...

  4. Go语言实现:【剑指offer】数组中的逆序对

    该题目来源于牛客网<剑指offer>专题. 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对10000 ...

  5. 【剑指offer】数组中的逆序对。C++实现

    原创文章,转载请注明出处! 博客文章索引地址 博客文章中代码的github地址 # 题目 # 思路 基于归并排序的思想统计逆序对:先把数组分割成子数组,再子数组合并的过程中统计逆序对的数目.统计逆序对 ...

  6. 剑指Offer 35. 数组中的逆序对 (数组)

    题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...

  7. [剑指Offer] 35.数组中的逆序对

    题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...

  8. 剑指offer:数组中的逆序对

    题目描述: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%100 ...

  9. 剑指offer——54数组中的逆序对

    题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...

随机推荐

  1. Why use MSIX message signal interrupt

    处理一个低版本内核中断向量表不够问题:__assign_irq_vector 关联irq 和 vector失败问题: (bug还没解决先记录一下吧) 同时先学习一下MSI-X:MSI, message ...

  2. 调度器简介,以及Linux的调度策略(转)

    进程是操作系统虚拟出来的概念,用来组织计算机中的任务.但随着进程被赋予越来越多的任务,进程好像有了真实的生命,它从诞生就随着CPU时间执行,直到最终消失.不过,进程的生命都得到了操作系统内核的关照.就 ...

  3. SpringBoot Redis切换数据库遇到的坑

    项目不同业务的redis数据存在不同的库中,操作数据需要切换redis库,在网上找了一段代码,确实可以切换数据库.但是使用一段时间后发现部分数据存储的数据库不正确,排查后发现setDatabase是线 ...

  4. ASP.NET Core管道详解[2]: HttpContext本质论

    ASP.NET Core请求处理管道由一个服务器和一组有序排列的中间件构成,所有中间件针对请求的处理都在通过HttpContext对象表示的上下文中进行.由于应用程序总是利用服务器来完成对请求的接收和 ...

  5. MongoDB动态建表方案(官方原生驱动)

    MongoDB动态建表方案(官方原生驱动) 需求前提:表名动态,表结构静态,库固定 1.导入相关依赖 <dependency> <groupId>org.mongodb< ...

  6. 怎么用MindManager制作议论文思维导图

    大家都写过作文吧,做小学到高考到大学,这是谁也摆脱不了的,但是大家写作文会提前把自己的思路整理出来吗?让自己行文更为顺畅,作文更为流利吗?特别是关于议论文,一直是高考写作的一个重点篇目,写好议论文,就 ...

  7. Python Api接口自动化测试框架 代码写用例

    公司新来两个妹子一直吐槽这个接口测试用例用excel维护起来十分费脑费事,而且比较low(内心十分赞同但是不能推翻自己),妹子说excel本来就很麻烦的工具,于是偷偷的进行了二次改版. 变更内容如下: ...

  8. 洛谷 P1360 [USACO07MAR]Gold Balanced Lineup G (前缀和+思维)

    P1360 [USACO07MAR]Gold Balanced Lineup G (前缀和+思维) 前言 题目链接 本题作为一道Stl练习题来说,还是非常不错的,解决的思维比较巧妙 算是一道不错的题 ...

  9. So Easy! HDU - 4565

    易知,有\(S_n = \lceil{a + \sqrt{b}}\rceil ^ n\) \(\because a ^ 2 - 1 < b < a ^ 2\) \(\therefore a ...

  10. OpenCV计算机视觉学习(12)——图像量化处理&图像采样处理(K-Means聚类量化,局部马赛克处理)

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 准备 ...