《剑指offer》——数组中的逆序对
来源:互联网 发布:费用优化例题 编辑:程序博客网 时间:2024/05/16 17:00
T:
题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
- 暴力搜索法
直接看代码,简洁明了。
code:
public int InversePairs(int [] array) { int nums = 0; for (int i = 1; i < array.length; i++) { for (int j = 0; j < i; j++) { if (array[j] > array[i]) { nums ++; } } } return nums;}
如果只是单纯的从暴力搜索的角度去解决该问题,貌似简单了点儿,且这种情况下的耗时为
看到讨论版的代码,很多人说用归并排序,对于这个排序,我也忘得差不多了,重新学习!
- more efficiency methods
先复习一下归并排序…
具体的算法思想不说了,给个链接:http://blog.csdn.net/morewindows/article/details/6678165/
code:
package niuke.sward2offer.inversePairs; /** * 归并排序,递归方式 * * date: 2015.11.11 22:00 * @author SSS * */ public class Solution1 { /** * 将两个有序数组合并为一个新数组,耗时O(n) * * @param array // 共用一个数组,即都在数组array上进行两个数组片段的重新排序 * @param aStart * @param aEnd * @param bStart * @param bEnd * @param newArray */ public void merge(int []array, int aStart, int aEnd, int bStart, int bEnd, int []newArray) { int i = aStart; int j = bStart; int count = 0; // 新数组的下标 while (i <= aEnd && j <= bEnd) { if (array[i] < array[j]) { newArray[count ++] = array[i ++]; } else { newArray[count ++] = array[j ++]; } } while (i <= aEnd) { newArray[count++] = array[i++]; } while (j <= bEnd) { newArray[count++] = array[j++]; } /** * 因为是要在下标为aStart和bEnd之间进行排序,所以将要有序的数列按对应下标覆盖array中原有的数据。 */ for (int k = 0; k < bEnd - aStart + 1; k++) { array[aStart + k] = newArray[k]; } } /** * 归并排序的主体部分 * @param array * @param start * @param end * @param newArray */ public void mergeSort(int []array, int start, int end, int []newArray) { if (start < end) { // 将下标为start和end这一部分的子数组从中间分为左、右两个部分 int mid = (start + end) / 2; mergeSort(array, start, mid, newArray); // 认为左边有序 mergeSort(array, mid + 1, end, newArray); // 认为右边有序 this.merge(array, start, mid, mid + 1, end, newArray); } } public static void main(String []args) { int []array = {6, 3, 5, 9, 1, 8, 2, 7, 10, 4}; int []newArray = new int[array.length]; Solution1 solution1 = new Solution1(); solution1.mergeSort(array, 0, array.length - 1, newArray); for (int i : newArray) { System.out.println(i); } } }
那么,能不能从这种方法的排序中得到点儿启发,从而算出原始数组中的逆序对呢?
归并排序的最底层,是从一个个的单个数字开始合并的,两个单个数字合并为一个二维有序数组,两个二维有序数组合并为一个有序的四维有序数组,……
归并排序的核心在于将两个有序数组合并为一个有序数组,代码如下:
/** * 将两个有序数组合并为一个新数组,耗时O(n) * * @param array // 共用一个数组,即都在数组array上进行两个数组片段的重新排序 * @param aStart * @param aEnd * @param bStart * @param bEnd * @param newArray */ public void merge(int []array, int aStart, int aEnd, int bStart, int bEnd, int []newArray) { int i = aStart; int j = bStart; int count = 0; // 新数组的下标 while (i <= aEnd && j <= bEnd) { if (array[i] < array[j]) { newArray[count ++] = array[i ++]; } else { newArray[count ++] = array[j ++]; } } while (i <= aEnd) { newArray[count++] = array[i++]; } while (j <= bEnd) { newArray[count++] = array[j++]; } /** * 因为是要在下标为aStart和bEnd之间进行排序,所以将要有序的数列按对应下标覆盖array中原有的数据。 */ for (int k = 0; k < bEnd - aStart + 1; k++) { array[aStart + k] = newArray[k]; } }
比如将两个有序数组:
假设
所以,在归并排序的过程中求解逆序对的方法如下:设置一个全局变量,用于统计每次调用merge(…)函数时存在的逆序对。
code:
package niuke.sward2offer.inversePairs; /** * 在归并排序上的改进,可求得数组中的逆序对。 * * date:2015.11.11 22:40 * @author SSS * */ public class Solution2 { private int inversePairsCount = 0; public int InversePairs(int [] array) { int []newArray = new int[array.length]; this.mergeSort(array, 0, array.length - 1, newArray); return inversePairsCount; } /** * 将两个有序数组合并为一个新数组,耗时O(n) * * @param array // 共用一个数组,即都在数组array上进行两个数组片段的重新排序 * @param aStart * @param aEnd * @param bStart * @param bEnd * @param newArray */ public void merge(int []array, int aStart, int aEnd, int bStart, int bEnd, int []newArray) { int i = aStart; int j = bStart; int count = 0; // 新数组的下标 while (i <= aEnd && j <= bEnd) { if (array[i] > array[j]) { newArray[count ++] = array[j ++]; inversePairsCount += aEnd - i + 1; // 将该轮合并当中出现的逆序对统计出来 } else { newArray[count ++] = array[i ++]; } } while (i <= aEnd) { newArray[count++] = array[i++]; } while (j <= bEnd) { newArray[count++] = array[j++]; } /** * 因为是要在下标为aStart和bEnd之间进行排序,所以将要有序的数列按对应下标覆盖array中原有的数据。 */ for (int k = 0; k < bEnd - aStart + 1; k++) { array[aStart + k] = newArray[k]; } } /** * 归并排序的主体部分 * @param array * @param start * @param end * @param newArray */ public void mergeSort(int []array, int start, int end, int []newArray) { if (start < end) { // 将下标为start和end这一部分的子数组从中间分为左、右两个部分 int mid = (start + end) / 2; mergeSort(array, start, mid, newArray); // 认为左边有序 mergeSort(array, mid + 1, end, newArray); // 认为右边有序 this.merge(array, start, mid, mid + 1, end, newArray); } } public static void main(String []args) { int []array = {5, 3, 4, 1}; Solution2 solution2 = new Solution2(); System.out.println("nums = " + solution2.InversePairs(array)); } }
- 剑指offer—数组中的逆序对
- 剑指offer—数组中的逆序对
- 《剑指offer》——数组中的逆序对
- 《剑指offer》——数组中的逆序对
- 剑指offer——数组中的逆序对
- 剑指Offer——(35)数组中的逆序对
- 剑指offer——数组中的逆序对
- 剑指Offer—35—数组中的逆序对
- 剑指offer——35.数组中的逆序对
- 剑指offer——数组中的逆序数对
- 剑指offer 面试题36—数组中的逆序对
- 【剑指offer】数组中的逆序对
- 剑指offer 36 数组中的逆序对
- 剑指offer--数组中的逆序对
- 剑指Offer之 - 数组中的逆序对
- 剑指offer之数组中的逆序对
- 剑指offer 36 - 数组中的逆序对
- 《剑指offer》数组中的逆序对
- 《算法导论》笔记&习题
- fopen与open的区别
- 报表开发工具中mysql数据库连接编码转化失效解决方案
- 子串
- IOS开发网络篇之──ASIHTTPRequest详解
- 《剑指offer》——数组中的逆序对
- c++异常处理机制
- boost::implicit_cast
- 链表-删除指定元素
- 第一次写博客,记录这一时刻
- Bitcode是什么?
- oslec.lib找不到解决办法
- Opengl投影矩阵和世界及局部坐标操作
- 双向队列