交易逆序对的总数 ---- 分治-归并

题目链接

题目:

分析:

  • 解法一: 暴力解法, 遍历所有的数对, 找到逆序对, 需要两重for循环, 一定会超时
  • 解法二: 归并排序的思想
  • 如果我们将数组分成两半, 我们在每一半中各找一个数字, 判断是否为逆序对, 再根据归并的思想, 再将一半数组分半, 判断是否为逆序对, 直到数组只有一个元素或一个元素也没有, 此时也不具有逆序对了
  • 如果我们再对数组进行归并排序, 归并排序有一个结论就是: 如果是升序排序, 当前的cur1前面的数字和cur2前面的数字一定是都小于cur1和cur2的
  • 策略一: 升序排序, 根据后面一半的数字cur2, 找出前面一半有多少个数字比它大
    如果这时nums[cur1] > nums[cur2] , 说明cur1前面的数字都不可能比cur2大, 而cur1后面的数字包括cur1都是比cur2大的, 所以我们可以利用升序排序, 轻松的找到多个逆序对, 即cur1到mid, 然后由于是升序, 需要将cur2放在tmp数组中, cur2++
    如果这时nums[cur1] <= nums[cur2], 说明cur1前面的数字包括cur1都不可能比cur2大, 后面的数我们还不知道, 所以只需将cur1++即可, 并在这之前根据归并排序的规则, 将此数放在tmp数组中
  • 同样, 如果是降序排序, 当前的cur1前面的数字和cur2前面的数字一定是都大于cur1和cur2的
  • 策略二: 降序排序, 根据前面一半的数字cur1, 找出后面一半有多少个数字比它小
    如果这时nums[cur1] > nums[cur2] , 说明cur2后面的数字包括cur2都比cur1小, 所以我们可以利用降序排序, 轻松的找到多个逆序对, 即cur2到right, 然后需要将cur1放在tmp数组中, cur1++
    如果这时nums[cur1] <= nums[cur2], 说明cur2前面的数字包括cur2都比cur1大,, 而cur2后面的数字还不知道, 然后由于是降序, 需要将cur2放在tmp数组中, cur2++

代码:

java 复制代码
class Solution {
    int[] tmp;

    public int reversePairs(int[] record) {
        tmp = new int[record.length];
        return mergeSort(record, 0, record.length - 1);
    }

    public int mergeSort(int[] nums, int left, int right) {
        if (left >= right)
            return 0;
        int ret = 0;
        int mid = left + ((right - left) >> 1);
        ret += mergeSort(nums, left, mid);
        ret += mergeSort(nums, mid + 1, right);
        int cur1 = left;
        int cur2 = mid + 1;
        int i = 0;
        while (cur1 <= mid && cur2 <= right) {
            if (nums[cur1] <= nums[cur2]) {
                tmp[i++] = nums[cur1++];
            } else {
                ret += mid - cur1 + 1;
                tmp[i++] = nums[cur2++];
            }
        }
        while (cur1 <= mid) {
            tmp[i++] = nums[cur1++];
        }
        while (cur2 <= right) {
            tmp[i++] = nums[cur2++];
        }
        for (int j = left; j <= right; j++) {
            nums[j] = tmp[j - left];
        }
        return ret;
    }
}
相关推荐
爱编程— 的小李几秒前
有序序列合并(c语言)
c语言·算法
云卓SKYDROID2 分钟前
无人机反步滑膜控制算法!
算法·无人机·知识科普·云卓科技·反步滑膜控制算法
云卓科技2 分钟前
无人机之自动控制原理篇
科技·算法·目标检测·机器人·无人机
云卓科技4 分钟前
无人机之集群控制方法篇
科技·算法·无人机·交互·制造
混迹网络的权某5 分钟前
每天一道C语言精选编程题之求数字的每⼀位之和
c语言·开发语言·考研·算法·改行学it·1024程序员节
Curry_Math9 分钟前
LeetCode 热题 100之链表3
算法·leetcode·链表
hn小菜鸡3 小时前
LeetCode 2058.找出临界点之间的最小和最大距离
算法·leetcode·职场和发展
liuyang-neu3 小时前
力扣 简单 70.爬楼梯
java·算法·leetcode
IronmanJay3 小时前
【LeetCode每日一题】——862.和至少为 K 的最短子数组
数据结构·算法·leetcode·前缀和·双端队列·1024程序员节·和至少为 k 的最短子数组
OT.Ter3 小时前
【力扣打卡系列】二分查找(搜索旋转排序数组)
算法·leetcode·职场和发展·go·二分查找