【十大排序】带你深入了解归并排序

简介: 【十大排序】带你深入了解归并排序

排序系列传递门

1. 了解

归并排序,是创建在归并操作上的一种有效的排序算法。算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。归并排序思路简单,速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。

一般求逆序对时,使用!!!

2. 图解

归并的精髓在于:分而治之

3. 代码分析

  1. 通过上面的图解,我们可以看到,归并排序是将一个数组拆分至一个,在利用Merge(归并)的思想,变成2个、4个、8个等
  2. 我们来想想,具体的代码应该怎么实现?
  3. 考虑当数组为0或1时的操作
public int reversePairs(int[] nums) {
    int len = nums.length;
    if (len < 2) {
      return 0; // 如果长度为1或者是0的话,则直接返回0
    }
    int[] temp = new int[len]; // 利用这个辅助数组来进行交换
    int[] copy = new int[len]; // 我们存储一个原来的数组,这样容易看出比较性
    for (int i = 0; i < len; i++) {
      copy[i] = nums[i];
    }
    // 这里我们的边界是[0,len-1],辅助数组为temp
    return reversePairs(copy, 0, len - 1, temp);
  }
  1. 我们怎么才能把一个数组分成一块一块,然后再合并呢?
    用到了递归的思想,我们想一想,终止条件是什么:当只剩下一个时,终止,也就是left == right,
    我们对左边进行reversePairs、对右边进行reversePairs,得到两个有序的数组
    对他们进行mergeAndCount,计算逆序对的值
public int reversePairs(int[] nums, int left, int right, int[] temp) {
    if (left == right) {
      return 0;
    }
    int mid = left + (right - left) / 2;
    int leftPairs = reversePairs(nums, left, mid, temp);
    int rightPairs = reversePairs(nums, mid + 1, right, temp);
    int crossPairs = mergeAndCount(nums, left, mid, right, temp);
    return leftPairs + rightPairs + crossPairs;
  }
  1. 再进行mergeAndCount,我们就要实现,两个有序的数组,怎么变成一个数组:双指针、依次比较即可
    这里注意两个地方:
    第一个是边界的处理,当i == mid + 1 或者 j == right + 1
    第二个是count(逆序对的处理)

    我们可以看到,5的值是大于4的,也就是5和7都是符合逆序对的,我们观察可以看出,逆序对的数量也就是左边数组剩余的个数:mid - i + 1
public int mergeAndCount(int[] nums, int left, int mid, int right, int[] temp) {
    for (int i = left; i <= right; i++) {
      temp[i] = nums[i];
    }
    int i = left;
    int j = mid + 1;
    int count = 0;
    for (int k = left; k <= right; k++) {
      if (i == mid + 1) {
        nums[k] = temp[i];
        i++;
      } else if (j == right + 1) {
        nums[k] = temp[j];
        j++;
      } else if (temp[i] <= temp[j]) {
        nums[k] = temp[i];
        i++;
      } else if (temp[i] > temp[j]) {
        nums[k] = temp[j];
        j++;
        count += mid - i + 1;
      }
    }
    return count;
  }
  1. 最后,我们得到这个逆序对的数值,我们来提交一下,看看可不可以通过~

    成功通过~~~

4.题目代码

// 手撕归并 -- 逆序对
public class Demo01 {
  public int reversePairs(int[] nums) {
    int len = nums.length;
    if (len < 2) {
      return 0; // 如果长度为1或者是0的话,则直接返回0
    }
    int[] temp = new int[len]; // 利用这个辅助数组来进行交换
    int[] copy = new int[len]; // 我们存储一个原来的数组,这样容易看出比较性
    for (int i = 0; i < len; i++) {
      copy[i] = nums[i];
    }
    // 这里我们的边界是[0,len-1],辅助数组为temp
    return reversePairs(nums, 0, len - 1, temp);
  }
  public int reversePairs(int[] nums, int left, int right, int[] temp) {
    if (left == right) {
      return 0;
    }
    int mid = left + (right - left) / 2;
    int leftPairs = reversePairs(nums, left, mid, temp);
    int rightPairs = reversePairs(nums, mid + 1, right, temp);
    int crossPairs = mergeAndCount(nums, left, mid, right, temp);
    return leftPairs + rightPairs + crossPairs;
  }
  public int mergeAndCount(int[] nums, int left, int mid, int right, int[] temp) {
    for (int i = 0; i < nums.length; i++) {
      temp[i] = nums[i];
    }
    int i = left;
    int j = mid + 1;
    int count = 0;
    for (int k = left; k <= right; k++) {
      if (i == mid + 1) {
        nums[k] = temp[i];
        i++;
      } else if (j == right + 1) {
        nums[k] = temp[j];
        j++;
      } else if (temp[i] <= temp[j]) {
        nums[k] = temp[i];
        i++;
      } else if (temp[i] > temp[j]) {
        nums[k] = temp[j];
        j++;
        count += mid - i + 1;
      }
    }
    return count;
  }
}


相关文章
|
6月前
|
机器学习/深度学习 算法 搜索推荐
八大排序(二)--------冒泡排序
八大排序(二)--------冒泡排序
21 1
|
6月前
|
算法 搜索推荐
八大排序--------(五)堆排序
八大排序--------(五)堆排序
17 0
|
6月前
|
机器学习/深度学习 搜索推荐
八大排序(三)--------简单选择排序
八大排序(三)--------简单选择排序
25 0
|
6月前
|
机器学习/深度学习 搜索推荐 算法
八大排序(四)--------直接插入排序
八大排序(四)--------直接插入排序
16 0
|
8月前
|
算法
八大排序——快速排序
八大排序——快速排序
|
11月前
|
存储 算法
十大排序之插入排序
十大排序之插入排序
61 0
|
12月前
|
存储 搜索推荐 算法
八大排序之插入排序和归并排序
八大排序之插入排序和归并排序
145 0
|
12月前
|
存储
八大排序之选择排序
八大排序之选择排序
9563 0
|
12月前
|
存储 搜索推荐 算法
八大排序之交换排序与计数排序 1
八大排序之交换排序与计数排序
71 0