算法导论学习1--分治法计算逆序数

原创 2011年09月06日 00:43:34

 闲来无事,复习复习经典的算法导论。看到了2-4,习题,计算逆序数的问题,忍不住实现了一下。

 

逆序数,是排列组合中常见的一个指标,可以用来衡量一个数列的杂乱成对(相对于顺序排列),在一些算法如水印算法中有广泛的应用。 如此如何快速的求得任意序列的逆

序数是关心的重点。常见的一种高效解法,是devid - and -conqure. 将序列平分成两段,分别计算逆序数,然后将两个有序的数列进行归并,并在归并过程中求取逆序数。两个

子序列的逆序数求取是较小规模的同样问题,可以用递归的方式完成。

 

简单说下如何在归并的过程中,计算逆序数。假设,有一个序列array[p, mid, r]. 其中array[p...mid], array[mid+1, ..., r]已经分别从小到大排好序。下面我们将两个子序列进行归

并。  假设当前的右边子序列(array[mid+1, ...., r])的当前待比较元素下表为right, 左边的为left, 当array[left] <= array[right], 这时候没有逆序发生(因为left的数 比right的

大)。当array[left] > array[right], 是,right指向的元素具有逆序数,个数为他之前的所有的数,即mid-left+1。如此遍历下去,即可得到在归并中得到逆序数。

 

算法非常简单直白。 复杂度为: T(n) = 2T(n/2) + O(n).  根据master定理, T(n) = O(nlogn). 空间复杂度为2n,当然可以更小,2logn。

 

附上java实现的源代码。

 

public class MergInversionCount {
	public static int count(int[] array, int p, int r) {
		int inversionCount = 0;
		if (p < r) {
			int mid = (p + r) / 2;
			inversionCount += count(array, p, mid);
			inversionCount += count(array, mid+1, r);
			inversionCount += mergeInversion(array, p, mid, r);
		}
		return inversionCount;
	}

	private static int mergeInversion(int[] array, int p, int mid, int r) {
		int inversionCount = 0;
		int[] temp = new int[r-p+1];
		if(array.length < r)
			return inversionCount;
		int left = p;
		int right = mid + 1;
		int storeIndex = 0;
		while(left <= mid && right <= r)
		{
			if(array[left] > array[right])
			{
				inversionCount += mid-left+1; //当前right存在逆序数,数目等于mid-left+1
				temp[storeIndex] = array[right];
				right++;
			}
			else
			{
				temp[storeIndex] = array[left];
				left++;
			}
			storeIndex++;
		}
		if(left <= mid)
		{
			for(int i = left; i <= mid; i++)
			{
				temp[storeIndex] = array[i];
				storeIndex++;
			}
		}
		if(right <= r)
		{
			for(int i = right; i <= r; i++)
			{
				temp[storeIndex] = array[i];
				storeIndex++;
			}
		}
		
		for(int i = p; i <= r; i++)
		{
			array[i] = temp[i-p];
			
		}
		return inversionCount;
	}

}



import static org.junit.Assert.*;

import org.junit.Test;

public class MergInversionCountTest {

	@Test
	public void testCount() {
		int[] array = {1,5,6,7,4};
		int[] array2 = {1,5,6,7,4,3,11, 15, 13, 2, 8};
		
		int inversionCount = MergInversionCount.count(array, 0, 4);
		assertTrue(inversionCount == 3 );
		
		inversionCount = MergInversionCount.count(array2, 4, 10);
		assertTrue(inversionCount == 10 );

	}

}


 

 

 

使用分治法计算逆序数——算法

/*----------------------------------------------- 名称:Use divide-and-couquer count the inversion 分治...
  • u013589337
  • u013589337
  • 2014年10月25日 22:06
  • 2015

分治法求解逆序数

在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。       求逆序数的方法很多。最容易想到的办法是...
  • dy01dy
  • dy01dy
  • 2014年07月25日 11:49
  • 1200

逆序数(分治)

问题:给定一个1~n的数组,求ia[j]的逆序对(i,j)的个数; 限制条件: 1 思路: 代码: typedef long long ll; //输入 vector A; ll me...
  • m0_37846371
  • m0_37846371
  • 2017年06月11日 00:08
  • 318

《算法导论》读书笔记(二)——分治法

设计算法 插入排序使用了增量法,即先排j-1个,然后排j个,下面学习一种新的方法:分治法。 分治法 分治法的思想:大事化小,分而治之。把规模较大的问题分解为几个规模较小的类似子问题,递归的求解子问题,...
  • vinson0526
  • vinson0526
  • 2013年09月02日 22:15
  • 907

利用分治法实现逆序数对的求解

给定一个数组N,求其中存在的逆序数对。 逆序数的定义,如果N[i]>N[j](i 求解思路: 1:暴力求解(从第一个元素开始遍历,遇到一个比其小的就记录一下)。 2:分治思想:归并排序的副产物,在Me...
  • u014594922
  • u014594922
  • 2017年10月13日 00:18
  • 166

MIT算法导论学习笔记-Lecture3:分治法

第三讲 分治法(Devide and Conquer)
  • ai552368625
  • ai552368625
  • 2014年07月25日 09:01
  • 1944

分治法求逆序对数目

设A[1..n]是一个包含n个不同整数的数组。如果在iA[j],则(i,j)就称为A中的一个逆序对(inversion)。 给出一个算法,确定n个元素的任何排列中逆序对的书目。时间复杂度为o(nlg...
  • u014082714
  • u014082714
  • 2015年03月27日 20:12
  • 1644

求序列逆序数

我就是随笔记一下。 首先,逆序数的定义我们在线性代数的课程中应该学到过:在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称...
  • u014097230
  • u014097230
  • 2016年08月08日 13:09
  • 667

分治法求一个N个元素数组的逆序数

转自:http://www.cnblogs.com/ChrisLi/p/3798858.html 分治法求一个N个元素数组的逆序数 背景      逆序数:也就是说,对于n个不同...
  • qq_26525317
  • qq_26525317
  • 2017年05月05日 19:06
  • 212

【算法导论】【笔记】【分治法】最近点对问题

寻找最近点对 目录 寻找最近点对 问题分析 分治法 时间复杂度 题目:在一个 n≥2n\geq 2 个点的集合 Q 中寻找距离最近的点对 问题分析 首先很容易想...
  • ideaqjx
  • ideaqjx
  • 2017年12月26日 16:30
  • 75
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:算法导论学习1--分治法计算逆序数
举报原因:
原因补充:

(最多只允许输入30个字)