lintcode:逆序对
2016-07-07 11:40
127 查看
题目
在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。给你一个数组,求出这个数组中逆序对的总数。
概括:如果a[i] > a[j] 且 i < j, a[i] 和 a[j] 构成一个逆序对。
样例
序列
解题
直接暴力找,时间复杂度O(n^2)
归并排序的思想
对于数组A[p,...,q]
分成两个数组A[p,...,r],A[r+1,...,q]
当这两个数组都是有序的时候,其逆序对数很好求
可以两个指针i,j分布指向数组的尾部
当A[i]>A[j]时候一定是逆序对,注意是有序的,逆序对数量:j-(r+1) +1 = j-r
else 不是逆序对
程序
分析下输出过程
测试样例:
5个元素划分的区间
元素下标上界是4
[0,4]划分[0,2]、[3,4]
---[0,2]划分:[0,1]、[2]
-------[0,1]划分:[0]、[1]
---[3,4]划分:[3]、[4]
输出情况
在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。给你一个数组,求出这个数组中逆序对的总数。
概括:如果a[i] > a[j] 且 i < j, a[i] 和 a[j] 构成一个逆序对。
样例
序列
[2, 4, 1, 3, 5]中,有 3 个逆序对
(2, 1),
(4, 1),
(4, 3),则返回
3。
解题
直接暴力找,时间复杂度O(n^2)
public class Solution { /** * @param A an array * @return total of reverse pairs */ public long reversePairs(int[] A) { // Write your code here long res = 0; int n = A.length; for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ if(A[i] >A[j]){ res ++; } } } return res; } }
归并排序的思想
对于数组A[p,...,q]
分成两个数组A[p,...,r],A[r+1,...,q]
当这两个数组都是有序的时候,其逆序对数很好求
可以两个指针i,j分布指向数组的尾部
当A[i]>A[j]时候一定是逆序对,注意是有序的,逆序对数量:j-(r+1) +1 = j-r
else 不是逆序对
程序
public class Solution { /** * @param A an array * @return total of reverse pairs */ long res = 0; public long reversePairs(int[] A) { // Write your code here int n = A.length; reversP(A,0,n-1); return res; } public void reversP(int[] A,int low,int high){ if(low>=high) return; int mid = low + (high - low)/2; reversP(A,low,mid); reversP(A,mid+1,high); merge(A,low,mid,high); } public void merge(int[] A,int low ,int mid ,int high){ int len = high - low + 1; int[] C = new int[len]; // 临时存放中间归并数组 int i = mid; int j = high; int k = len -1; while(i>= low && j>=mid+1){ if(A[i] > A[j]){ C[k--] = A[i]; i--; res += j - (mid + 1) +1; // 逆序对数量 }else{ C[k--] = A[j]; j--; } } while(i>=low){ C[k--] = A[i]; i--; } while(j>=mid+1){ C[k--] = A[j]; j--; } for(k=0;k<len;k++){ A[k+low] = C[k]; } } public void print(int[] A){ for(int a:A){ System.out.print(a+"\t"); } System.out.println(); } }
分析下输出过程
测试样例:
[2,4,1,3,5]
5个元素划分的区间
元素下标上界是4
[0,4]划分[0,2]、[3,4]
---[0,2]划分:[0,1]、[2]
-------[0,1]划分:[0]、[1]
---[3,4]划分:[3]、[4]
输出情况
2 4 1 3 5 最底层只有一个元素 1 2 4 3 5 [0,2]合并 1 2 4 3 5 1 2 3 4 5 [0,4]合并
算法可行性 一个数组分成B、C两部分,B、C两部分分布升序排序 对于A[i] 在B中,A[j]在C中的情况,关于A[i]与A[j]的逆序对数量与B中A[i]的位置、C中A[j]的位置无关,这个很显然 程序开始的时候找到是1个元素,后来合并成两个元素的数组,这样慢慢的合并,并计算逆序对的数量,最后就得到答案了
相关文章推荐
- java实现的读写锁
- iOS 获取设备信息
- 战争
- 绘制多边形
- Git学习笔记
- colojure语言基础入门
- Apache common包应用集合
- Java类型擦除
- Entity Framework 6.0 Tutorials(2):Async query and Save
- JavaScript 仿ios滑动选择器
- div+ul
- 关于库文件的制作和区别
- TextView 文字滚动 跑马灯效果
- 【DM8168学习笔记5】EZSDK目录结构
- HTML的文本设置
- hog.compute()
- 动画性能提升
- 使用context.Request.Files出现错误: 上传失败,错误信息:SyntaxError: Unexpected number
- (C)strcpy ,strncpy与strlcpy
- Extjs3.0整合ssh时提交表单,总是执行failure函数,不知道为什么,请各位大虾指教! [