当前位置: 首页 > article >正文

剑指 Offer 51. 数组中的逆序对

剑指 Offer 51. 数组中的逆序对

 

【归并】朴实无华的一个归并排序的应用,对于一个数组,我们通过归并排序来从大到小进行排序,在合并的过程中如果前面区间有比后面区间大的元素,那么后面区间从这个元素开始一直到结束都能和前面区间的那个数组成逆序对。

举个🌰:

7,5,6,4,3

我们知道归并排序是先划分然后再合并,最底层的肯定就是单个元素,所以一开始的时候:(啊不对,还是算一算区间划分吧,第一层[0, 2] [3, 4], 第二层[0, 1] [2] [3] [4], 第一个划分第三层)

第三层:[7], [5]

归并的时候我们发现7 > 5,说明组成了一个逆序对。合并后是[7, 5];

第二层:先合并[7, 5], [6] 再合并 [4], [3];

7 > 6, 增加一个逆序对;合并为[7, 6, 5];

4 > 3, 增加一个逆序对;合并为[4, 3]。

第一层合并[7, 6, 5]和[4, 3]

7 > 4,增加两个逆序对,注意这里是两个,因为4后面肯定比4还小,另外此时7已经归并到最终数组去了;

6 > 4,再增加两个逆序对;

5 > 4,再增加两个逆序对。

所以总结下来,这个的精髓就是在归并A,B区间的过程中,如果发现A区间的元素a>B区间的元素b,那么B区间从b开始剩下的元素肯定能和a组成逆序对(在归并过程中a和b都是现存的区间的最顶元素了)。

class Solution {

    // 归并 4:38 5

    int ans = 0, n;
    int[] nums, tmp; 

    void mergeSort(int l, int r){
        if(l >= r) return;
        int mid = (l + r) >>> 1;
        mergeSort(l, mid); mergeSort(mid + 1, r);
        int i = l, j = mid + 1, k = 0;
        while(i <= mid && j <= r){
            if(nums[i] > nums[j]){
                ans += (r - j + 1);
                tmp[k++] = nums[i++];
            }else{
                tmp[k++] = nums[j++];
            }
        }
        while(i <= mid) tmp[k++] = nums[i++];
        while(j <= r) tmp[k++] = nums[j++];
        for(i = l, j = 0; j < k; i++, j++) nums[i] = tmp[j];
    }

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


http://www.kler.cn/a/16726.html

相关文章:

  • STM32问题集
  • androidstudio下载gradle慢
  • CSS多列布局:打破传统布局的束缚
  • AI 写作(五)核心技术之文本摘要:分类与应用(5/10)
  • IPguard与Ping32全面对比——选择最适合企业的数据安全解决方案
  • 2024.11.12_大数据的诞生以及解决的问题
  • 计算机视觉 | 人工智能 自己总结 (下)
  • 数据库之事务隔离级别详解
  • 08.watchEffect.上
  • CTF权威指南 笔记 -第二章二进制文件-2.1-汇编原理
  • r语言tidyverse教程:3数据重塑tidyr
  • Baumer工业相机堡盟相机如何使用偏振功能(偏振相机优点和行业应用)(C#)
  • MySQL数据库中,在读已提交和可重复读这两个不同事务隔离级别下幻读的区别
  • 来CSDN两年了,一些小感想
  • 第十八章 协程
  • Vue父组件生命周期和子组件生命周期触发顺序
  • Reactive响应式编程系列:解密reactor-netty如何实现响应式
  • Java 基础入门篇(一)—— Java 概述
  • CF1060E Sergey and Subway
  • 并发编程之Atomic原子操作类
  • 【华为OD机试真题】计算网络信号 (javaC++python)100%通过率 超详细代码注释
  • 【计算机视觉】ViT:代码逐行解读
  • linux入门---软硬链接
  • 支持轴体热插拔的平价机械键盘,全尺寸带灯效,雷柏V700DIY上手
  • linux 设置开机启动不同方式
  • Linux系统中查看日志的命令