1 题目描述

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

2 思路和方法

  利用归并排序的思想,先把数组分隔成子数组,先统计出子数组内部的逆序对的数目,然后再统计出两个相邻子数组之间的逆序对的数目。注意在合并两个已排序的子数组后,要更新数组。O(n*log(n))。

3 C++核心代码

 class Solution {
public:
int InversePairs(vector<int> data) {
if(data.size() <= )
return ;
int count = ;
vector<int> copy(data); // 初始化
InversePairsCore(data, copy, , data.size()-,count);
return count;
} // 归并
void InversePairsCore(vector<int> &data, vector<int> &copy, int start, int end, int &count){
if(start>=end){
return;
}
int mid = (start + end) /;
InversePairsCore(data,copy,start,mid,count);
InversePairsCore(data,copy,mid+,end,count); int copyIndex = end; // 将较大数字从后往前复制到辅助数组
int i = mid; // 前半段最后一个元素下标
int j = end; // 后半段最后一个元素下标
while (i>=start && j>=mid+) {
if (data[j] < data[i]){ // 逆序
count += j - mid;
count %= ; // 取模防止逆序对溢出
copy[copyIndex--] = data[i--];
} else{
copy[copyIndex--] = data[j--];
}
} while (i>=start)
copy[copyIndex--] = data[i--]; while (j>=mid+)
copy[copyIndex--] = data[j--]; for (int k = start; k <= end; ++k)
data[k] = copy[k]; }
};

4 C++完整代码

 #include<iostream>
using namespace std;
//数组中的逆序对
long long GetMergePairsBetween(int* arr,int* copy,int start,int mid,int end)
{
//合并两个子数组,并计算逆序对个数
int final1 = mid;//第一个数组的最后一位
int final2 = end;//第二个数组的最后一位
int index = end;//辅助数组的最后一位
long long count = ;
while(final1 >= start && final2 >= mid+)//两个数组都没有处理完
{
if(arr[final1] > arr[final2])
{
//如果第一个数组的元素大于第二个数组的任何元素,
//则第一个数组的元素一定大于第个数组中final2之前的所有元素
count += (final2 - mid);
//将final1处的元素拷贝至copy数组
//index和final1都向前移动
copy[index--] = arr[final1--];
}
else
{
//第一个数组的元素小于第二个数组的元素
//第二个数组的元素拷贝至copy数组
//并将index和final2前移
copy[index--] = arr[final2--];
}
}
while(final1 >= start)//第一个数组的元素没有处理完
{
copy[index--] = arr[final1--];
}
while(final2 >= mid + )//第一个数组的元素没有处理完
{
copy[index--] = arr[final2--];
}
for(int i = end; i > index;i--)
arr[i] = copy[i];
return count;
}
long long GetMergePairs(int* arr,int* copy,int start,int end)
{
long long ret = ;
if(start < end)
{
int mid = start + ((end - start)>>);
ret += GetMergePairs(arr,copy,start,mid);
ret += GetMergePairs(arr,copy,mid+,end);
ret += GetMergePairsBetween(arr,copy,start,mid,end);
}
return ret;
}
long long GetTotalPairs(int arr[],int n)
{
if(arr == NULL || n < )
return ;
int* copy = new int[n];
long long sum = GetMergePairs(arr,copy,,n-);
delete[] copy;
return sum;
}
int main()
{
int arr[] = {,,,};
int ret = GetTotalPairs(arr,sizeof(arr)/sizeof(arr[]));
cout<<ret<<endl;
system("pause");
return ;
}

参考资料

https://blog.csdn.net/zjwreal/article/details/88769617

https://blog.csdn.net/DERRANTCM/article/details/46761051(图)

https://blog.csdn.net/peiyao456/article/details/54645952(完整代码)

剑指offer35:数组中的逆序对的更多相关文章

  1. [剑指OFFER] 数组中的逆序对

    题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数.     分析:利用归并排序的思想,分成2部分,每一部分按照从大到 ...

  2. 剑指offer_数组中的逆序对

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

  3. 剑指Offer——数组中的逆序对

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

  4. 剑指Offer-34.数组中的逆序对(C++/Java)

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

  5. 用js刷剑指offer(数组中的逆序对)

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

  6. 剑指Offer——数组中的逆序对(归并排序的应用)

    蛮力: 遍历数组,对每个元素都往前遍历所有元素,如果有发现比它小的元素,就count++. 最后返回count取模. 结果没问题,但超时哈哈哈,只能过50%.   归并法: 看讨论,知道了这道题的经典 ...

  7. 剑指 Offer——数组中的逆序对

    1. 题目 2. 解答 借助于归并排序的分治思想,在每次合并的时候统计逆序对.因为要合并的两个数组都是有序的,如果左半部分数组当前值大于右半部分数组当前值,那么左半部分数组当前值右边的数就都大于右半部 ...

  8. 剑指Offer34 数组中的逆序对

    /************************************************************************* > File Name: 34_Invers ...

  9. 剑指offer-数组中的逆序对-数组-python

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

  10. 剑指offer--35.数组中只出现一次的数字

    时间限制:1秒 空间限制:32768K 热度指数:198150 本题知识点: 数组 题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. class ...

随机推荐

  1. java集合类-Set接口

    Set集合 Set集合中的对象不按特定的方式排序,只是简单的把对象放入集合中,但是不能包含重复对象. Set集合由Set接口和Set接口的实现类组成,Set接口继承与于Collection接口 Set ...

  2. windows游戏编程地址

    本系列文章由jadeshu编写,转载请注明出处.http://blog.csdn.net/jadeshu/article/details/22309325 作者:jadeshu   邮箱: jades ...

  3. 利用Python爬取朋友圈数据,爬到你开始怀疑人生

    人生最难的事是自我认知,用Python爬取朋友圈数据,让我们重新审视自己,审视我们周围的圈子. 文:朱元禄(@数据分析-jacky) 哲学的两大问题:1.我是谁?2.我们从哪里来? 本文 jacky试 ...

  4. OpenPyXl的使用

    OpenPyXl的使用 开始在内存中使用 创建一个workbook 在刚开始使用openpyxl的时候,不需要直接在文件系统中创建一个文件,仅仅需要导入Workbook类并开始使用它: >> ...

  5. 二十三、Linux任务计划及周期性任务执行:at、crontab命令

    一.概述 未来的某时间点执行一次某任务:at, batch周期性运行某任务:crontab 这两个任务的执行结果:会通过邮件发送给用户 (本地终端用户之间的邮件通知) centos 5,6,7默认开启 ...

  6. AE开发之txt转shp

    实现坐标txt文件转shp点集数据文件的窗体Form txt格式为:首行为“id,x,y” 第二行开始输入具体数值:id,x,y(x,y为具体的xy坐标) using System; using Sy ...

  7. CF1208D

    CF1208D 题意: 给你一个数组,要求支持单点修改和单点查询 解法: 直接线段树搞一搞就没了. CODE: #include<iostream> #include<cstdio& ...

  8. 手写alert弹框(一)

    采用原生的JavaScript, html代码 <meta name="viewport" content="width=device-width, initial ...

  9. 使用 Linux Mint 作为主要操作系统的一些个人常用软件

    本篇文章讲一下一些 Linux 上的应用,多数为日常生活娱乐用的软件,同时也会讲一点开发工具,对于有兴趣继续研究 Linux 的可以参考一下. 目录 软件的安装方式 1.Software Manage ...

  10. zookeeper源码 — 五、处理写请求过程

    目录 处理写请求总体过程 客户端发起写请求 follower和leader交互过程 follower发送请求给客户端 处理写请求总体过程 zk为了保证分布式数据一致性,使用ZAB协议,在客户端发起一次 ...