微软面试题:剑指 Offer 51. 数组中的逆序对 Hard 出现次数:3
题目描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。
输入一个数组,求出这个数组中的逆序对的总数。
示例 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的更多相关文章
- 剑指 Offer 51. 数组中的逆序对 + 归并排序 + 树状数组
剑指 Offer 51. 数组中的逆序对 Offer_51 题目描述 方法一:暴力法(双层循环,超时) package com.walegarrett.offer; /** * @Author Wal ...
- 【Java】 剑指offer(51)数组中的逆序对
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成 ...
- 【剑指offer】数组中的逆序对
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/mmc_maodun/article/details/27520535 转载请注明出处:http:// ...
- Go语言实现:【剑指offer】数组中的逆序对
该题目来源于牛客网<剑指offer>专题. 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对10000 ...
- 【剑指offer】数组中的逆序对。C++实现
原创文章,转载请注明出处! 博客文章索引地址 博客文章中代码的github地址 # 题目 # 思路 基于归并排序的思想统计逆序对:先把数组分割成子数组,再子数组合并的过程中统计逆序对的数目.统计逆序对 ...
- 剑指Offer 35. 数组中的逆序对 (数组)
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
- [剑指Offer] 35.数组中的逆序对
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
- 剑指offer:数组中的逆序对
题目描述: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%100 ...
- 剑指offer——54数组中的逆序对
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
随机推荐
- Cephfs的文件存到哪里了
前言 在ceph里面使用rbd接口的时候,存储的数据在后台是以固定的prifix的对象存在的,这样就能根据相同的前缀对象去对image文件进行拼接或者修复 在文件系统里面这一块就要复杂一些,本篇就写的 ...
- SpringBoot WebSocket 消息交互
1. Websocket原理 Websocket协议本质上是一个基于TCP的独立协议,能够在浏览器和服务器之间建立双向连接,以基于消息的机制,赋予浏览器和服务器间实时通信能力. WebSocket资源 ...
- Unity Lod
LOD是Level Of Detais 的简称,多细节层次,根据摄像机与物体距离,unity会自动切换模型.一般离摄像机近的时候显示高模,离摄像机远的时候显示低模,借此来提升性能. 如果你在Blend ...
- App安全常见漏洞修复建议
ios开发对自己的app做一系列的环境检测 检测Cydia是否安装 检测app是否可以编辑系统文件 检测系统是否包含可疑的文件 检测是否有可疑的app安装如:FakeCarrier, Icy, etc ...
- jboss反序列化漏洞实战渗透笔记
一.利用shodan,fofa或谷歌搜索关键字:8080/jmx-console/ 二.下载java反序列化终极测试工具进行验证漏洞 三.记住User Current Directory: C:\j ...
- 防sql注入函数
- Talk About My Route To Edit
Initially, I plan to write 4 columns:Python, Qt, Linux,and respectively, Career. However, my ambitio ...
- zk与eureka区别
cap永远的神!
- 小叶入门之Python爬虫(一)
一.Python简洁的简介 Python是一种跨平台的计算机程序设计语言.它是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言.最初被设计用于编写自动化脚本(shell),随着版本的不断更 ...
- SkyWalking —— 分布式应用监控与链路追踪
SkyWalking 是一个应用性能监控系统,特别为微服务.云原生和基于容器(Docker, Kubernetes, Mesos)体系结构而设计.除了应用指标监控以外,它还能对分布式调用链路进行追踪. ...