【LeetCode】剑指 Offer 51. 数组中的逆序对 p249 -- Java Version

news2024/11/17 17:45:52

题目链接:https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/

1. 题目介绍(51. 数组中的逆序对)

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

在这里插入图片描述

【测试用例】:
示例 1:

输入: [7,5,6,4]
输出: 5

【条件约束】:

限制

  • 0 <= 数组长度 <= 50000

2. 题解

2.1 枚举 – O(n2)

时间复杂度O(n2),空间复杂度O(1)

解题思路】:
该题最直接的思路就是 枚举顺序扫描整个数组,每扫描到一个数字,逐个比较该数字和它后面的数字的大小。如果后面的数字比它小,则这两个数字就组成一个逆序对。假设数组中含有 n 个数字。由于每个数字都要和 O(n) 个数字进行比较,因此这种算法的时间复杂度是 O(n2)
……
实现策略】:

  1. 定义变量 n,用来记录输入数组长度,然后以此进行无效输入判断;
  2. 定义变量 count,用来记录这个数组中逆序对的总数;
  3. 实现双重循环,让每个数字都与其后面的所有数字进行比较;
  4. 循环结束,返回 count.
class Solution {
    // Soultion1:枚举
    public int reversePairs(int[] nums) {
        // 定义变量 n,用来记录输入数组长度
        int n = nums.length;
        // 无效输入判断
        if (n <= 1) return 0;
        // 定义变量 count,用来记录这个数组中逆序对的总数
        int count = 0;
        // 双重循环,让每个数字都与其后面的所有数字进行比较
        for (int i = 0; i < n; i++) {
            for (int j = i+1; j < n; j++) {
                if (nums[i] > nums[j]) count++;
            }
        }
        // 循环结束,返回结果
        return count;
    }
}

在这里插入图片描述

2.2 归并排序 – O(nlogn)

时间复杂度O(nlogn),空间复杂度O(n)

解题思路】:
以数组 {7,5,6,4} 为例来分析统计逆序对的过程。每扫描到一个数字的时候,我们不能拿它和后面的每一个数字进行比较,否则时间复杂度就是
O(n2),因此我们可以 考虑先比较两个相邻的数字
……
依据这种思想,我们可以将数组进行以下四步的操作,即:

  • 拆分
  • 合并
  • 统计
  • 排序

其中合并和统计可以一块进行。
……
而这个排序的过程实际上就是 归并排序,归并排序可参考:【算法】排序算法之归并排序
……
合并过程可参考:
在这里插入图片描述

  • 合并阶段 本质上是 合并两个排序数组 的过程,而每当遇到 左子数组当前元素 > 右子数组当前元素 时,意味着 「左子数组当前元素 至 末尾元素」 与 「右子数组当前元素」 构成了若干 「逆序对」,同时,我们要将较小的那个元素存入临时数组中

……
实现策略】:

  1. 利用数组长度 n 进行无效输入判断;
  2. 对数组 nums 进行归并排序;
    • 递归划分左右区域;
    • 合并、判断、排序;

在这里插入图片描述

class Solution {
    // Soultion2:归并排序
    int[] nums;
    public int reversePairs(int[] nums) {
        // 定义变量 n,用来记录输入数组长度
        int n = nums.length;
        // 无效输入判断
        if (n <= 1) return 0;
        // 初始化数组
        this.nums = nums;
        // 定义变量 count,用来记录这个数组中逆序对的总数
        int count = mergeSort(nums,0,n-1);
        // 循环结束,返回结果
        return count;
    }

    public int mergeSort(int[] nums,int l,int r){
        // 当只有一个节点的时候,直接返回,退出递归
        if(l >= r) return 0;
        // 递归划分
        int mid = l + (r - l) / 2;
        // 左拆分
        int left = mergeSort(nums,l,mid);
        // 右拆分
        int right = mergeSort(nums,mid+1,r);
        // 合并
        int count = merge(nums,l,mid,r);
        // 返回最终结果
        return left + right + count;
    }

    public int merge(int[] nums,int left,int mid,int right){
        int count = 0;
        // 定义一个临时数组
        int[] temp = new int[right-left+1];
        // 定义一个指针,指向第一个数组的第一个元素
        int i = left;
        // 定义一个指针,指向第二个数组的第一个元素
        int j = mid+1;
        // 定义一个指针,指向临时数组的第一个元素
        int t = 0;
        // 当两个数组都有元素的时候,遍历比较每个元素大小
        while(i <= mid && j <= right){
            // 比较两个数组的元素,取较小的元素加入到,临时数组中
            // 并将两个指针指向下一个元素
            if(nums[i] <= nums[j]){
                temp[t++] = nums[i++];
            }else{
                // 当左边数组的大与右边数组的元素时,就对当前元素以及后面的元素的个数进行统计,
                // 此时这个数就是,逆序数
                // 定义一个计数器,记下每次合并中存在的逆序数。
                count += mid-i+1;
                temp[t++] = nums[j++];
            }
        }
        // 当左边的数组没有遍历完成后,直接将剩余元素加入到临时数组中
        while(i <= mid){
            temp[t++] = nums[i++];
        }
        // 当右边的数组没有遍历完成后,直接将剩余元素加入到临时数组中
        while(j <= right){
            temp[t++] =nums[j++];
        }
        // 将新数组中的元素,覆盖nums旧数组中的元素。
        // 此时数组的元素已经是有序的
        for(int k =0; k< temp.length;k++){
            nums[left+k] = temp[k];
        }
        return count;
    }
}

在这里插入图片描述

3. 参考资料

[1] 剑指 Offer 51. 数组中的逆序对(归并排序,清晰图解)
[2] 排序——归并排序(Merge sort)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/419625.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python3 DataFrame一些好玩且高效的操作

pandas在处理Excel/DBs中读取出来&#xff0c;处理为DataFrame格式的数据时&#xff0c;处理方式和性能上有很大差异&#xff0c;下面是一些高效&#xff0c;方便处理数据的方法。 map/apply/applymaptransformagg遍历求和/求平均shift/diff透视表切片&#xff0c;索引&#x…

VS Code 将推出更多 AI 功能给 Java 开发者

大家好&#xff0c;欢迎来到我们的二月更新&#xff01;我们将为您带来与 JUnit 5 并行测试相关的新功能以及用于 Spring Boot Dashboard 的过滤功能。另外&#xff0c;OpenAI 和 ChatGPT 是最近的热点&#xff0c;所以在 GitHub Copilot 方面也有一些令人激动的消息&#xff0…

【郭东白架构课 模块二:创造价值】19|节点二:架构活动的目标为什么常常被忽略?

你好&#xff0c;我是郭东白。从这节课开始&#xff0c;我们就进入到架构活动第二个环节的学习&#xff0c;那就是目标确认。 为架构活动确认一个正确目标&#xff0c;是架构师能为架构活动做出最大贡献的环节。从我的个人经验来看&#xff0c;一大半架构活动的目标都不具备正…

类文件具有错误的版本 55.0, 应为 52.0

最近在编译时报如下错误 java: 无法访问com.xx错误的类文件: /xxx.jar!/aa.class类文件具有错误的版本 55.0, 应为 52.0请删除该文件或确保该文件位于正确的类路径子目录中。 原来我依赖的jar包的编译版本是jdk11,而我本地代码编译的版本的jdk1.8,两个版本不一致&#xff0c;所…

C++类和对象终章——友元函数 | 友元类 | 内部类 | 匿名对象 | 关于拷贝对象时一些编译器优化

文章目录&#x1f490;专栏导读&#x1f490;文章导读&#x1f337;友元&#x1f33a;概念&#x1f33a;友元函数&#x1f341;友元函数的重要性质&#x1f33a;友元类&#x1f341;友元类的重要性质&#x1f337;内部类&#xff08;不常用&#xff09;&#x1f33a;内部类的性…

Ubuntu 下载并切换Python默认版本(无痛顺畅版)

Ubuntu 下载并切换Python默认版本的方法 文章目录Ubuntu 下载并切换Python默认版本的方法一&#xff0c;前言二&#xff0c;在ubantu中下载指定python版本1&#xff0c;更新apt版本为最新2&#xff0c;安装software-properties-common3&#xff0c;将 deadsnakes PPA 添加到你的…

并发 并行 进程 线程

并发 并行 进程 线程 进程和线程介绍 程序、进程和线程的关系示意图 并发和并行 1)多线程程序在单核上运行&#xff0c;就是并发 2)多线程程序在多核上运行&#xff0c;就是并行 示意图: 小结

大模型时代的“Linux”生态,开启人工智能新十年

演讲 | 林咏华 智源人工智能研究院副院长 整理 | 何苗出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;2018 年以来&#xff0c;超大规模预训练模型的出现推动了 AI 科研范式从面向特定应用场景、训练专有模型&#xff0c;转变为大模型微调模型服务的AI工业化开…

016 - 如何写一个 C++ 类

到目前为止&#xff0c;我们学了类 class&#xff0c;本期我们要尝试着从头开始写一个类。 本期不会讲的太深。我们不会写非常复杂的类&#xff0c;我们要会完成一个基本的 log 类&#xff0c;来演示一下我们已经学过的相关知识。 接下来的几期&#xff0c;我们会继续学习类。…

银行数字化转型导师坚鹏:《银行业金融机构数据治理指引》

《银行业金融机构数据治理指引》 ——“监”听则明 护航银行高质量发展课程背景&#xff1a; 很多金融机构存在以下问题&#xff1a; 不清楚《银行业金融机构数据治理指引》出台背景&#xff1f; 不知道如何理解《银行业金融机构数据治理指引》相关规定&#xff1f; 不清楚…

重生之我是孔乙己——查找数组缺失元素的几种方法

&#x1f48c; 博客内容&#xff1a;查找缺失元素 &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准前端&#xff0c;专注基础和实战分享 &#xff0c;欢迎私信&#xff01; &#x1f496; 欢迎大家&#xff1a;这里是…

【MySQL | 基础篇】03、MySQL 约束

目录 一、概述 二、约束演示 三、外键约束 3.1 介绍 3.2 语法 3.3 删除/更新行为 一、概述 概念: 约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 目的&#xff1a;保证数据库中数据的正确、有效性和完整性。 分类&#xff1a; 注意&#xff1a…

千耘农机导航的“星地一体”能力究竟是什么?

伴随农业机械化和智能化的发展&#xff0c;越来越多的人开始使用农机自动驾驶系统助力耕作&#xff0c;千耘农机导航的“星地一体”能力可有效解决信号受限的问题&#xff0c;实现作业提效。究竟什么是“星地一体”&#xff0c;又是如何解决智能化农机作业的痛点的&#xff1f;…

CTFHub | 00截断

0x00 前言 CTFHub 专注网络安全、信息安全、白帽子技术的在线学习&#xff0c;实训平台。提供优质的赛事及学习服务&#xff0c;拥有完善的题目环境及配套 writeup &#xff0c;降低 CTF 学习入门门槛&#xff0c;快速帮助选手成长&#xff0c;跟随主流比赛潮流。 0x01 题目描述…

Java模拟星空

目录 前言 JavaFX基础 1. GraphicsContext 2. AnimationTimer 代码实现 完整代码 前言 看了Python模拟星空很漂亮&#xff0c;Java也应该必须有一个&#xff01; 环境&#xff1a;只需要JDK1.8就好&#xff01;不需要外部包&#xff01;&#xff01;&#xff01; Jav…

力扣-《剑指offer》-简单题

目录 第一题&#xff1a;05.替换空格 第二题&#xff1a;06.从尾到头打印链表 第三题&#xff1a;11.旋转数组的最小数字​编辑 第四题&#xff1a;17.打印从1到最大的n位数 第五题&#xff1a;29.顺时针打印矩阵 第六题&#xff1a;53.在排序数组中查找数字 第七题&#…

【C++】关于多线程,你应该知道这些

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《吃透西嘎嘎》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;多线程相…

Python自动化测试 环境搭建 详解

一、安装Python环境&#xff1a; Python环境目前已被大部分主流操作系统所支持&#xff0c;比如在Linux、Mac、Unix等系统上就自带了Python环境&#xff0c;但在Windows系统上目前还需要自己安装。 1、下载Python Python下载地址&#xff1a;https://www.python.org/downloads…

Flink 1.14测试cdc写入到kafka案例

测试案例 1、遇到的问题 1.1 bug1 io.debezium.DebeziumException: Access denied; you need (at least one of) the REPLICATION SLAVE privilege(s) for this operation Error code: 1227; SQLSTATE: 42000.at io.debezium.connector.mysql.MySqlStreamingChangeEventSour…

网络编程(第一章:网络基础)

文章目录一. 网络基础1.2 联网协议和层1.2.1 网络采用分层的思想1.2.2 OSI体系结构&#xff08;重点&#xff01;&#xff01;)1.2.3 TCP/IP协议1.2.3.1 网络接口与物理层1.2.3.2 网络层1.2.3.3 传输层1.2.3.4 应用层1.2.4 网络封包与拆包1.3 TCP和UDP的异同点&#xff08;重点…