码迷,mamicode.com
首页 > 编程语言 > 详细

数组中的逆序对

时间:2015-08-18 12:11:06      阅读:344      评论:0      收藏:0      [点我收藏+]

标签:剑指offer   归并排序   逆序对   

题目

在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对,输入一个数组,求出这个数组中的逆序对的总数。
例如:{7,5,6,4},一共存在5个逆序对,分别是(7,6)(7,5)(7,4)(6,4)和(5,4)

思路

本来是毫无思路的,一般习惯了暴力破解,剑指offer后面的归并排序的思想,让我想到归并排序是好多年前写过的(忘了......果然出来混总是要还的)。
归并排序的思想是利用分治法,将一个很大的问题,缩小成一个很小的问题,将很长的数组,最终递归分成两个数进行比较。
逆序对刚好可以利用这一点,当剩两个数的时候,判断前面的是否大于后面的,如果大于后面的,那么就是一个逆序对,而且后面的一般都是排好序的,所以我们让指针从后面开始往前遍历,只要前半部分的数据大于后半部分的最后一个,那么就会大于所有后半部分的。

如图:
技术分享
(图片来自:http://blog.csdn.net/cjf_iceking/article/details/7920153)

第一层排好序后,回到第二层,这时候我们判断95 和84的大小,95>84,就说明95大于84之前所有的,所以此时的逆序对数就是84加上之前所有的元素个数。
然后计算完成后,反着放入新数组,这样后边就不会再次累积了,这其实借用了归并排序的思想。

代码

public static int InversePair(int[] data,int start,int end,int[] temp)
	{
		int count=0;  //累积逆序对的总数
		if(start < end)
		{
 
		   int mid = (end+start)/2;
		
		   count +=  InversePair(data, start, mid ,temp);
		   count +=  InversePair(data,mid+1,end,temp);
		   count += getInversePair(data,start,mid,end,temp);
		  
		}    
		
		return count;
	}
	
	
	
	private static int getInversePair(int[] data, int start,int mid, int end,int[] temp) 
	{
		int i=mid;    //前半部分的末尾
		int count=0; 
		int j = end;  //后半部分的末尾
		int index=0;
		while(i >=start && j>mid)
		{
			if(data[i] > data[j])
			{
				temp[index++] = data[i--];
				count += j-mid;  //j之前的所有元素都是逆序对数
				
			}
			else
			{
				temp[index++] = data[j--];
				 
			}
			
		}
		
		while(i>=start)
		{
			temp[index++] = data[i--];
		 
		}
		
		while(j>mid)
		{
			temp[index++] = data[j--];
			 
		}
		//将其排好序的放入原数组
		for(int k=0;k<index;k++)
		{
			data[end-k] = temp[k];
		}
	 
	 	 
		
		return count;
	}




版权声明:本文为博主原创文章,转载请注明出处。

数组中的逆序对

标签:剑指offer   归并排序   逆序对   

原文地址:http://blog.csdn.net/u014307117/article/details/47747277

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!