用divide&conquer思想解决求逆序数对的问题
2009-10-24 01:58
387 查看
对于一个给定的数组中要去求其中逆序数对的个数,可以通过简单的两层for循环去逐个便利每一个数对,这样的思想是很容易就可以想到
的,但是其算法的复杂度确是O(n^2),为了降低算法的复杂度可以试着用divide&conquer思想去考虑这个问题。
对于一个数组{5,3,7,4,6,2,1,8},如果我们以中间(或者左中)为界限将其分成两个数组,只要知道这两个数组中的逆序对数和两边
的数所组成的逆序对数就是它所有的逆序对数了。而数组划分的递归结束点在两个数组都只有一个元素的时候,因此两数组中的逆序对数可以
通过递归求得。要去求分裂的两数组中的逆序对数可以这样去做:先将两数组按升序排序,若前一个数组的第一个元素比后一个的大,则说
明前一组的后面所有都要比后一组的第一个元素大,这样将较小的第一个元素去掉后,继续比较两个数组的第一个元素可以把所有的逆序对找
到。
下面是该算法的JAVA实现:
import java.util.*;
public class CountInversedNumbers{
public static int count=0; //记录逆序对个数;
public void sort_count(int []L){
int n=L.length;
int a=(int)(n/2+0.5);
int b=(int)(n/2);
int A[]=new int[a];
int B[]=new int[b];
for (int i=0;i<a;i++)
A[i]=L[i];
for (int j=0;j<b;j++)
B[j]=L[j+a]; //把单个数组划分成两个数组;
if(a>1&&b>1) {
sort_count(A);
sort_count(B); //递归的划分数组;
}
Arrays.sort(A);
Arrays.sort(B); //将数组排序;
merge_count(A,B);
}
public void merge_count(int []M, int[]N){ //求被划分的两个数组中元素组成的逆序对;
int c=M.length;
int d=N.length;
while(c>0&&d>0)
{
if(M[0]>N[0]) {
this.count=this.count+c;
for(int i=0;i<d-1;i++)
N[i]=N[i+1];
d--;
}
else{
for(int j=0;j<c-1;j++)
M[j]=M[j+1];
c--;
}
}
}
public static void main(String[] args){
int K[]={6,2,3,5,7,1,4,8};
CountInversedNumbers a=new CountInversedNumbers();
a.sort_count(K);
System.out.println(a.count); //输出结果是11;
}
}
的,但是其算法的复杂度确是O(n^2),为了降低算法的复杂度可以试着用divide&conquer思想去考虑这个问题。
对于一个数组{5,3,7,4,6,2,1,8},如果我们以中间(或者左中)为界限将其分成两个数组,只要知道这两个数组中的逆序对数和两边
的数所组成的逆序对数就是它所有的逆序对数了。而数组划分的递归结束点在两个数组都只有一个元素的时候,因此两数组中的逆序对数可以
通过递归求得。要去求分裂的两数组中的逆序对数可以这样去做:先将两数组按升序排序,若前一个数组的第一个元素比后一个的大,则说
明前一组的后面所有都要比后一组的第一个元素大,这样将较小的第一个元素去掉后,继续比较两个数组的第一个元素可以把所有的逆序对找
到。
下面是该算法的JAVA实现:
import java.util.*;
public class CountInversedNumbers{
public static int count=0; //记录逆序对个数;
public void sort_count(int []L){
int n=L.length;
int a=(int)(n/2+0.5);
int b=(int)(n/2);
int A[]=new int[a];
int B[]=new int[b];
for (int i=0;i<a;i++)
A[i]=L[i];
for (int j=0;j<b;j++)
B[j]=L[j+a]; //把单个数组划分成两个数组;
if(a>1&&b>1) {
sort_count(A);
sort_count(B); //递归的划分数组;
}
Arrays.sort(A);
Arrays.sort(B); //将数组排序;
merge_count(A,B);
}
public void merge_count(int []M, int[]N){ //求被划分的两个数组中元素组成的逆序对;
int c=M.length;
int d=N.length;
while(c>0&&d>0)
{
if(M[0]>N[0]) {
this.count=this.count+c;
for(int i=0;i<d-1;i++)
N[i]=N[i+1];
d--;
}
else{
for(int j=0;j<c-1;j++)
M[j]=M[j+1];
c--;
}
}
}
public static void main(String[] args){
int K[]={6,2,3,5,7,1,4,8};
CountInversedNumbers a=new CountInversedNumbers();
a.sort_count(K);
System.out.println(a.count); //输出结果是11;
}
}
相关文章推荐
- VS2005 解决"应用程序配置不正确,程序无法启动"问题(小问题,大思想)
- 用“道”的思想解决费用流问题---取/不取皆是取 (有下界->有上界) / ACdreamoj 1171
- 第十周项目3-用二叉树遍历思想解决问题(1)&(2)
- 解决ADB server didn't ACK问题,连上手机问题
- "SQL Server不存在或访问被拒绝"问题解决
- 第十周 项目三 利用二叉树遍历思想解决问题(4)
- 解决build path contains duplicate entry:'src' for project 'XXX'问题
- [zz]说说"解决问题团队的有效组织"(17章)
- 关于在英创em9161板上使用ADO.net连接远程数据库提示 “无法找到 PInvoke dll"dbnetlib.dll"”问题解决方法
- 解决ios、微信移动端的position: fixed; 支持性不好的问题 && 禁用下拉暴露黑底的功能
- Swift2.0后"|" cannot be applied to two operands问题解决方法
- undefined reference to 'pthread_create'问题解决
- cocos2d-x xcode提示错误:"vtable for XXX", referenced from 问题解决;
- jquery attr 设定src中含有&(宏)符号问题的解决方法
- PHP的header("P3P: CP=CURa……")解决Cookie跨域问题
- 进入'我的电脑'窗口后,左边显示的‘系统任务,其它位置,详细信息’菜单条到删除和出现的问题解决
- 在Eclipse中编写servlet时出现"The import javax.servlet cannot be resolved" 问题解决办法
- "cannot be resolved or is not a field"问题解决
- 用合并排序算法解决逆序数问题
- 解决方法:SQL2008 链接服务器 访问接口 "SQLNCLI10" 的架构行集 出错的问题!