归并排序的新用法。

26 篇文章 0 订阅

1,题目: 

此题暴力写的话很简单,但是这是困难题,暴力时间复杂度坑定是过不去的,不可以哦。

2,归并新用法。

归并排序不讲哦:讲新奇的用法

看图:在归的过程中不断算出红色方框的逆序对,不断的从下往上算逆序对,并不断累加就ok了。

为什么是对的呢,因为是对应位置的,不会重复的逆序对被统计。其次最终要的是归并排序在归并的时候是有序的,俩个有序的归成一个有序的,我们要求出那俩个有序的组成的逆序对,就非常简单了。效率也就非常高了,利用了有序的性质,非常的巧妙。。

3.代码实现

关键部位都有注释,如果还有问题的话,可以一步leetcode 官方解释。

力扣

class Solution {
public:
    int mergeSort(vector<int>& nums, vector<int>& tmp, int l, int r) {
        if (l >= r) {
            return 0;
        }

        int mid = (l + r) / 2;
        int inv_count = mergeSort(nums, tmp, l, mid) + mergeSort(nums, tmp, mid + 1, r);
        int i = l, j = mid + 1, pos = l;
        
        //第一种情况。 都没完
        while (i <= mid && j <= r) {
            
            if (nums[i] <= nums[j])
            {
                tmp[pos] = nums[i];
                ++i;        //左开右闭 正好是我们需要的个数。
                inv_count += (j - (mid + 1));
            }
            else
            {
                tmp[pos] = nums[j];
                ++j;
            }
            
            ++pos;
        }
        //第二中情况处理。   后面先完了。
        for (int k = i; k <= mid; ++k) {
            tmp[pos++] = nums[k];
            
            inv_count += (j - (mid + 1));
        }
        //第三种情况   前面先完了。
        for (int k = j; k <= r; ++k) {
            tmp[pos++] = nums[k];
        }
        
        //把归并好的有序元素拷贝回原来的位置。    为什么不在原来数组上归并呢???因为会有数据覆盖,不可以在原来数组归并。。
        //把前面的拷贝到后面中去。 左闭 右开    
        //加的是l 不是 1
        copy(tmp.begin() + l, tmp.begin() + r + 1, nums.begin() + l);
        
        //返回当前归并的个数。
        return inv_count;
    }

    int reversePairs(vector<int>& nums) {
        int n = nums.size();
        vector<int> tmp(n);
        return mergeSort(nums, tmp, 0, n - 1);
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
归并排序是一种常见的排序算法,它采用分治的思想,将一个大问题分解为多个小问题进行解决,最后将结果合并得到最终的排序结果。下面是Java中使用归并排序的示例代码: ```java public class MergeSort { public static void mergeSort(int[] arr) { if (arr == null || arr.length <= 1) { return; } int[] temp = new int[arr.length]; mergeSort(arr, 0, arr.length - 1, temp); } private static void mergeSort(int[] arr, int left, int right, int[] temp) { if (left < right) { int mid = (left + right) / 2; mergeSort(arr, left, mid, temp); // 对左半部分进行归并排序 mergeSort(arr, mid + 1, right, temp); // 对右半部分进行归并排序 merge(arr, left, mid, right, temp); // 合并左右两部分 } } private static void merge(int[] arr, int left, int mid, int right, int[] temp) { int i = left; // 左序列指针 int j = mid + 1; // 右序列指针 int t = 0; // 临时数组指针 while (i <= mid && j <= right) { if (arr[i] <= arr[j]) { temp[t++] = arr[i++]; } else { temp[t++] = arr[j++]; } } while (i <= mid) { // 将左边剩余元素填充进temp中 temp[t++] = arr[i++]; } while (j <= right) { // 将右序列剩余元素填充进temp中 temp[t++] = arr[j++]; } t = 0; // 将temp中的元素全部拷贝到原数组中 while (left <= right) { arr[left++] = temp[t++]; } } } ``` 使用归并排序时,可以调用`mergeSort`方法传入待排序的数组即可完成排序。在`mergeSort`方法中,首先判断数组是否为空或长度小于等于1,如果是,则直接返回。然后创建一个临时数组`temp`,并调用`mergeSort`方法进行递归排序。在递归排序的过程中,将数组分为左右两部分,分别对左右两部分进行归并排序,最后调用`merge`方法将左右两部分合并起来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LYH_1_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值