【HackerRank】Insertion Sort Advanced Analysis(归并排序求数列逆序数对)
Insertion Sort is a simple sorting technique which was covered in previous challenges. Sometimes, arrays may be too large for us to wait around for insertion sort to finish. Is there some other way we can calculate the number of times Insertion Sort shifts each elements when sorting an array?
If ki is the number of elements over which ith element of the array has to shift then total number of shift will be k1 + k2 + ... + kN.
Input:
The first line contains the number of test cases T. T test cases follow. The first line for each case contains N, the number of elements to be sorted. The next line contains N integers a[1],a[2]...,a[N].
Output:
Output T lines, containing the required answer for each test case.
Constraints:
1 <= T <= 5
1 <= N <= 100000
1 <= a[i] <= 1000000
好恶心的题,从早上做到现在才过,整个人昏昏沉沉的,还没从昨天20多个小时车程中恢复过来T_T
ok,来说说这道题,是要求insertion sort时数组中元素移动的次数。最naive的方法当然是直接进行一边insertion sort,输出移动次数了,这个复杂度是O(N2),会超时。
其实,Insertion Sort中元素移动的次数和这个序列中逆序数的和是相等的。因为,在把元素a[i]插入数组的过程中,已经排好序的部分数组中比它大的元素都要后移。
所以我们的问题就简化为怎样快速的求出一个序列的逆序数。网上的方法很多:Binary Search Tree(当树为单支二叉树的时候算法复杂度退化到O(N2),红黑树,归并排序等等。
这里采用归并排序的方法:在归并排序的归并这一步时候,由两个数组ar1和ar2,它们分别是原数组的前半部分和后半部分。每次取ar1和ar2数组头部最小的元素插入到排好序的数组中,当这个最小元素是从ar2中取出的时候,ar1中当前游标之后的元素都比这个最小元素大,而且在原数组中位于这个元素前面,所以此时一共输出m-point1对逆序数(m是ar1的长度,point1是当前ar1的游标)。这样我们就可以在归并排序的过程中统计出逆序数对了。
举个例子:

如上图所示,左边的图显示了整个归并过程中统计逆序数的过程。橙色的数字表示在每次归并中输出的逆序数对,最后把数出的所有逆序数对相加即可。
右边的图显示了具体合并(1,7)和(2,9)的过程,第二步要合并2的时候,发现在第一个数组中有个7比2大,那么此时(7,2)就是序列的一对逆序数。
最后一个细节是,当ar1和ar2的头部元素相等的时候,那么直接取ar1头部元素放入归并后的数组就可以了。
代码如下:
import java.util.*;
public class Solution {
private static long answer = 0;
private static int[] Merge(int[] ar1,int[] ar2){
int m = ar1.length;
int n = ar2.length;
int point1 = 0;
int point2 = 0;
int index_result = 0;
int[] result = new int[m+n];
while(point1 < m && point2 < n){
if(ar1[point1] < ar2[point2]){
result[index_result] = ar1[point1];
point1++;
index_result++;
}
else if(ar1[point1] > ar2[point2]){
answer += m - point1;
result[index_result] = ar2[point2];
index_result++;
point2++;
}
else{
result[index_result] = ar1[point1];
index_result++;
point1++;
}
}
while(point1 < m){
result[index_result] = ar1[point1];
index_result++;
point1++;
}
while(point2 < n){
answer += m - point1;
result[index_result] = ar2[point2];
index_result++;
point2++;
}
return result;
}
private static int[] mergeSort(int[] ar){
int n = ar.length;
if(n <= 1)
return ar;
int mid = n/2;
int[] ar1 = new int[mid];
int[] ar2 = new int[n-mid];
System.arraycopy(ar, 0, ar1, 0, mid);
System.arraycopy(ar, mid, ar2, 0, n-mid);
int[] sorted_ar1 = mergeSort(ar1);
int[] sorted_ar2 = mergeSort(ar2);
int[] result = Merge(sorted_ar1, sorted_ar2);
return result;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int T = in.nextInt();
for(int k = 0;k < T;k++){
answer = 0;
int n = in.nextInt();
int[] ar = new int[n];
for(int i = 0;i < n;i++)
ar[i] = in.nextInt();
mergeSort(ar);
System.out.println(answer);
}
}
}
【HackerRank】Insertion Sort Advanced Analysis(归并排序求数列逆序数对)的更多相关文章
- 线段树解Insertion Sort Advanced Analysis
题目出处 题意描述: 这个题目提问的是,在插入排序的序列给定的情况下,求最少需要移动的次数. 序列的长度n <=10^5 序列中的元素a[i] <=10^6 一组数据中case数t < ...
- 【归并排序】【逆序数】HDU 5775 Bubble Sort
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 题目大意: 冒泡排序的规则如下,一开始给定1~n的一个排列,求每个数字在排序过程中出现的最远端 ...
- HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)
HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意: 给一个序列由 ...
- Reduce inversion count 求最小逆序数
本问题出自:微软2014实习生及秋令营技术类职位在线测试 (Microsoft Online Test for Core Technical Positions) Description Find a ...
- HDU2838 Cow Sorting 树状数组 区间求和加逆序数的应用
这题目意思非常easy,就是给你一个数组,然后让你又一次排好序,排序有要求的,每次仅仅能交换两个元素的位置,交换须要一个代价 就是两个元素之和,问你把数组重小到大排好最少须要多少代价 可能一開始想不到 ...
- hdu-1394(线段树求最小逆序数)
http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意: 给定一个n,然后又n个数字,首先,这些数字的大小是从0开始到n-1,比如样例n=10,则这十个数就 ...
- 归并排序(包含逆序数对的个数51Nod1019)
归并排序是效率很好的排序方式,和快排效率一样高,但在稳定性上优于快排,下面我们来介绍归并排序. 归并排序运用递归将序列不断二分(其原理就是分治),就像一棵树不断向下分支,最后分到只剩一个元素,这样这个 ...
- hdu1394Minimum Inversion Number(线段树,求最小逆序数)
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
- poj 1804 (nyoj 117)Brainman : 归并排序求逆序数
点击打开链接 Brainman Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 7810 Accepted: 4261 D ...
随机推荐
- 2017 Wuhan University Programming Contest (Online Round) Lost in WHU 矩阵快速幂 一个无向图,求从1出发到达n最多经过T条边的方法数,边可以重复经过,到达n之后不可以再离开。
/** 题目:Lost in WHU 链接:https://oj.ejq.me/problem/26 题意:一个无向图,求从1出发到达n最多经过T条边的方法数,边可以重复经过,到达n之后不可以再离开. ...
- 【ASP.NET】——AdRotator控件
AdRotator控件即广告控件. 广告,是站点不可缺少的一部分.也是站点获取收益的最主要途径,但最初制作广告非常麻烦.asp.net就将该方法封装成了一个控件.为我们节省了非常多时间.这也是ASP. ...
- java 提取数据
import java.util.regex.Matcher; import java.util.regex.Pattern; public class TextNested { public sta ...
- 面试题:谈谈你对hibernate的理解
说说这类问题一般要和一个东西比較.说说他们的长处和缺点,hibernate就和JDBC比較呗.你就说说JDBC的优缺点.然后说说hibernate的优缺点,最后对照得出hibernate更好. hib ...
- PostgreSQL tips
tip 1 在sql中我们可以设置一个列自增长identity(1,1),但在postgresql中却没有这个关键字定义.但postgresql也有实现相关功能,那就是只需要将该列数据类型标记为ser ...
- 48、ViewFlow ---- 滑动广告页
<!-- main.xml --> <?xml version="1.0" encoding="utf-8"?> <LinearL ...
- std::condition_variable(3)复习
#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> ...
- 安装mysql报错—解决方法:error while loading shared libraries: libssl.so.6
for 32bit ln -sf /usr/lib/libssl.so.10 /usr/lib/libssl.so.6ln -sf /usr/lib/libcrypto.so.10 /usr/lib/ ...
- 获取html元素所在页面的坐标
function findPosition(oElement) { var x2 = 0; var y2 = 0; var width = oElement.offsetWidth; var heig ...
- redis集群报错,(error) MOVED 15495 127.0.0.1:7003
节点会对命令请求进行分析和key的slot计算,并且会查找这个命令所要处理的键所在的槽.如果要查找的哈希槽正好就由接收到命令的节点负责处理, 那么节点就直接执行这个命令. 另一方面, 如果所查 ...