zoukankan      html  css  js  c++  java
  • 算法之逆序对

    算法之逆序对

    逆序对问题

    ​ 假设A[1..n]是一个有n个不同数的数组。若i<j且A[i]>A[j],则对偶(i, j)称为A的一个逆序对(inversion)。

    1. 列出数组{2, 3, 8, 6, 1}的5个逆序对
    2. 由集合{1, 2, ..., n}中的元素构成的什么数组具有最多的逆序对?它有多少逆序对?
    3. 插入排序的运行时间与输入数组中的逆序对的数量有什么关系?
    4. 给出一个求在n个元素的任何排列中逆序对数量的算法,最坏时间复杂度为: (Theta)(nlgn)
    1. 根据定义易得,逆序对为:(2, 1)、(3, 1)、(8, 6)、(8, 1)、(6, 1)

    2. 当数组元素恰好为n个元素从大到小排列时,拥有最多的逆序对。此时逆序对为: (n - 1) + (n -2) + (n - 3) + ... + 1 = n(n - 1) / 2

    3. 根据插入排序的实现过程,不难得出每次从未排序数组选择一个值arr[j]插入已排序数组的时候,所需要的移动次数,即为以arr[j]为右侧值的逆序对的个数。这个特性也可以设计出一个时间复杂度为: (Theta)((n^2))的算法。当然这种指数级别复杂度的算法我们直接PASS

    4. 不难想到(Theta)(nlgn)算法复杂度的归并排序。其实归并排序在分治的时候不会改变逆序对的个数。只有在合并的时候,才会因为逆序对的出现导致右侧提前被合入原数组。其实修改点主要在两个方面:

    • 声明一个全局变量用来存储总的次数
    • 在右侧提前被合入原数组的时候对总次数进行累加(只需要改归并排序的merge方法, 归并排序请参照http://www.cnblogs.com/Kidezyq/p/8379267.html

    具体源代码如下:

    private static int count;
    
    private static void merge(int[] arr, int startIndex, int midIndex, int endIndex) {
    	/**
    	 * 合并策略: 
    	 * 1. 新建两个数组,分别存取左半部分排好序的数组和右半部分排好序的数组
    	 * 2. 分别从左右两个数组最开始下标开始遍历,选取较小的依次放入原数组对应位置
    	 * 3. 最终如果左右数组中有一个已经遍历完成,另一个数组所剩的元素直接放入元素组后面部分即可
    	 */
    	// STEP1
    	int[] leftArr = new int[midIndex - startIndex];
    	int[] rightArr = new int[endIndex - midIndex];
    	System.arraycopy(arr, startIndex, leftArr, 0, leftArr.length);
    	System.arraycopy(arr, midIndex, rightArr, 0, rightArr.length);
    	
    	// STEP2
    	int k = startIndex;	// 存储原数组中的下标
    	int i = 0; 			// 存储左边数组的下标
    	int j = 0;			// 存储右边数组的下标
    	while (i < leftArr.length && j < rightArr.length) {
    		// 将较小的元素复制到元素组对应下标k,并且移动较小元素所在数组下标
    		if (leftArr[i] < rightArr[j]) {
    			arr[k++] = leftArr[i++];	
    		} else {
    			// 此时说明 arr[i]到arr[leftArr.length - 1]的值都比arr[j]大,即此时以arr[j]结尾的逆序对个数为: 
    			count += leftArr.length - i;
    			arr[k++] = rightArr[j++];
    		}
    	}
    	
    	// STEP3
    	if (i < leftArr.length) {
    		System.arraycopy(leftArr, i, arr, k, leftArr.length - i);
    	} else if (j <= rightArr.length) {
    		System.arraycopy(rightArr, j, arr, k, rightArr.length - j);
    	}
    }
    
    
  • 相关阅读:
    HTML里使用CSS 的几种方式?
    Dmoz介绍及怎么提交?
    delphi实现自动填写表单和调用网页上的函数
    SEO之Head标签
    location.replace()和location.href=的区别?
    css几种选择器举例
    如何让百度认为你的站是一个好网站?
    桌面被恶意软件放上几个ie图标删除不了怎么办?
    Delphi正则表达式使用方法(TPerlRegEx)
    mysql中limit的用法详解(数据分页常用)
  • 原文地址:https://www.cnblogs.com/Kidezyq/p/8379332.html
Copyright © 2011-2022 走看看