题目:

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

输入描述:

题目保证输入的数组中没有的相同的数字

数据范围:

对于%50的数据,size<=10^4

对于%75的数据,size<=10^5

对于%100的数据,size<=2*10^5

分析:

可以从头扫描整个数组,每扫描到一个数字,就去计算后面的数字有多少比它小,这样操作的话时间复杂度是O(n^2),应该会超时。

我们可以利用归并排序时合并两个有序的数组时候,更快的求得每次合并时的逆序对。

例如合并[5,7]和[4,6]时从两个数组后面开始比较,选出较大的元素。

因为7>6,所以7一定大于第二个数组剩下的所有元素,因为数组本身是有序的,可以立刻得到逆序对的个数,当后面的元素大时,不需要统计逆序对的个数,因为此时要大于前面剩下的所有元素,不构成逆序对。基于这种方法,时间复杂度控制在O(nlogn)。

程序:

C++

class Solution {
public:
int InversePairs(vector<int> data) {
return mergesort(data, , data.size()-)%;
}
long long mymerge(vector<int> &vec, int left, int mid, int right){
vector<int> temp(right-left+,);
int index = right-left;
long long countnum = ;
int i = mid;
int j = right;
while(i >= left && j >= mid+){
if(vec[i] > vec[j]){
countnum += (j-mid);
temp[index--] = vec[i--];
}
else{
temp[index--] = vec[j--];
}
}
while(i >= left)
temp[index--] = vec[i--];
while(j >= mid+)
temp[index--] = vec[j--];
for(int i = ; i < temp.size(); ++i)
vec[i+left] = temp[i];
return countnum;
}
long long mergesort(vector<int> &vec, int left, int right){
if(left >= right)
return ;
int mid = (left + right) / ;
long long leftCount = mergesort(vec, left, mid);
long long rightCount = mergesort(vec, mid+, right);
long long res = mymerge(vec, left, mid, right);
return res + leftCount + rightCount;
}
};

Java

public class Solution {
public int InversePairs(int [] array) {
return (int)(mergesort(array, , array.length-)%);
}
public static long mymerge(int [] array, int left, int mid, int right){
int[] temp = new int[right-left+];
int index = right-left;
long countnum = ;
int i = mid;
int j = right;
while(i >= left && j >= mid+){
if(array[i] > array[j]){
countnum += (j-mid);
temp[index--] = array[i--];
}
else{
temp[index--] = array[j--];
}
}
while(i >= left)
temp[index--] = array[i--];
while(j >= mid+)
temp[index--] = array[j--];
for(i = ; i < temp.length; ++i)
array[i+left] = temp[i];
return countnum;
}
public static long mergesort(int [] array, int left, int right){
if(left >= right)
return ;
int mid = (left + right) / ;
long leftCount = mergesort(array, left, mid);
long rightCount = mergesort(array, mid+, right);
long res = mymerge(array, left, mid, right);
return res + leftCount + rightCount;
}
}

剑指Offer-34.数组中的逆序对(C++/Java)的更多相关文章

  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 51. 数组中的逆序对 Hard 出现次数:3

    题目描述: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对. 输入一个数组,求出这个数组中的逆序对的总数. 示例 1: 输入: [7,5,6,4] 输出: 5 限制: ...

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

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

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

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

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

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

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

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

随机推荐

  1. Java中的substring()用法

    String str = "Hello Java World!"; Method1:  substring(int beginIndex) 返回从起始位置(beginIndex)至 ...

  2. 路由器配置深入浅出—路由器接口PPP协议封装及PAP和CHAP验证配置

    知识域: 是针对点对点专线连接的接口的二层封装协议配置 PPP的PAP和CHAP验证,cpt支持,不一定要在gns3上做实验. 路由器出厂默认是hdlc封装,修改为ppp封装后,可以采用pap验证或者 ...

  3. pymssql默认关闭自动模式开启事务行为浅析

    使用Python采集SQL Server数据库服务器磁盘信息时,遇到了一个错误"CONFIG statement cannot be used inside a user transacti ...

  4. C++学习笔记14_C#调用dll

    1. 首先C++创建dll项目,各种调第三方库,把这些东西都弄好后,整一个导出接口,例如: extern "C" __declspec(dllexport) int Add(int ...

  5. 学习笔记24_MVC前后台数据交互

    *最普通的交互方式,在Contoller中的Action方法内 public ActionResult Index() { ViewData["Key"] =Value; Retu ...

  6. [考试反思]1102csp-s模拟测试98:苟活

    好像没有什么粘文件得分的必要(本来就没多少分了也丢不了多少了) 而且从这次开始小绿框不代表首杀而代表手速了2333 其实我挺菜的,牛一个frepoen送掉100分才跟我并列%%%milkfun mik ...

  7. 单点登录 - OAuth 2.0 授权码模式(一)

    OAuth 2.0定义了四种授权方式 授权码模式(authorization code) 简化模式(implicit) 密码模式(resource owner password credentials ...

  8. 11、pytest -- 测试的参数化

    目录 1. @pytest.mark.parametrize标记 1.1. empty_parameter_set_mark选项 1.2. 多个标记组合 1.3. 标记测试模块 2. pytest_g ...

  9. NOIP模拟14-16

    最近事情有些多,先咕了! 鸽了,时间太久远了,写了话坑太大,太费时间了!

  10. 『题解』洛谷P3384 【模板】树链剖分

    Problem Portal Portal1: Luogu Description 如题,已知一棵包含\(N\)个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作\(1\): ...