【Leetcode每日一题】 分治 - 交易逆序对的总数(难度⭐⭐⭐)(74)

news2024/12/23 6:50:24

1. 题目解析

题目链接:LCR 170. 交易逆序对的总数

这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。

2.算法原理

归并排序的基本思路

归并排序将数组从中间分成两部分,在排序的过程中,逆序对的来源分为以下三类:

  1. 左子数组内部的逆序对
  2. 右子数组内部的逆序对
  3. 跨越左右子数组的逆序对

最终的逆序对总数是这三类逆序对的总和。归并排序的整体步骤如下:

  1. 排序左子数组
  2. 排序右子数组
  3. 合并两个有序子数组
利用归并排序统计逆序数的原理

在归并排序的合并过程中,左、右子数组始终保持有序状态。我们可以利用这一特性快速统计跨越左右子数组的逆序对数量,而不必遍历所有可能的组合。

具体计算逆序数的方法

合并两个有序数组时,可以通过以下两种方式之一统计逆序数:

  1. 统计某个数之前的有多少个数比它大
  2. 统计某个数之后的有多少个数比它小

我们重点分析第一种方式的原理。

示例分析

假设两个有序数组和辅助数组为 left = [5, 7, 9]right = [4, 5, 8]help = []。通过合并的过程可以求得逆序数。定义如下变量:

  • cur1:遍历 left 数组的指针
  • cur2:遍历 right 数组的指针
  • ret:记录逆序数的计数器

合并的具体步骤如下:

  1. 第一轮left[cur1] > right[cur2]。因为 left 数组中 [cur1, 2] 区间的所有元素均大于 right[cur2],这些元素可以与 right[cur2] 构成逆序对。因此,更新 ret += 3 并将 right[cur2] 放入 help 数组,同时 cur2++

  2. 第二轮left[cur1] == right[cur2]。此时 right[cur2] 可能与 left 中的其他元素形成逆序对,因此将 left[cur1] 放入 help 数组。没有新增逆序对,不更新 ret

  3. 第三轮left[cur1] > right[cur2]。与第一轮类似,left[cur1, 2] 区间内的元素均大于 right[cur2],更新 ret += 2,并将 right[cur2] 放入 help 数组,cur2++

  4. 第四轮left[cur1] < right[cur2]left[cur1]right 中的所有元素小,不构成逆序对。直接将 left[cur1] 放入 help 数组,不更新 ret

  5. 第五轮left[cur1] > right[cur2]。此时 left 中的元素能与 right[cur2] 构成逆序对,更新 ret += 1,并将 right[cur2] 放入 help 数组。

处理剩余元素

在合并过程中,如果 left 中还有剩余元素,说明这些元素已经与 right 中的元素计算过,不会新增逆序对。直接将剩余元素放入 help 数组。如果 right 中还有剩余元素,则这些元素均比 left 中的元素大,同样不会构成逆序对。

小结

通过上述方式利用归并排序的合并过程,可以快速统计逆序数。复杂度为 O(N log N),相较于暴力解法的 O(N^2) 效率更高。

3.代码编写

class Solution {
    int tmp[50010];

public:
    int reversePairs(vector<int>& nums) {
        return mergeSort(nums, 0, nums.size() - 1);
    }
    int mergeSort(vector<int>& nums, int left, int right) {
        if (left >= right)
            return 0;
        int ret = 0;
        // 1. 找中间点,将数组分成两部分
        int mid = (left + right) >> 1;
        // [left, mid][mid + 1, right]
        // 2. 左边的个数 + 排序 + 右边的个数 + 排序
        ret += mergeSort(nums, left, mid);
        ret += mergeSort(nums, mid + 1, right);
        // 3. ⼀左⼀右的个数
        int cur1 = left, cur2 = mid + 1, 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++];
            }
        }
        // 4. 处理⼀下排序
        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;
    }
};

The Last

嗯,就是这样啦,文章到这里就结束啦,真心感谢你花时间来读。

觉得有点收获的话,不妨给我点个吧!

如果发现文章有啥漏洞或错误的地方,欢迎私信我或者在评论里提醒一声~

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

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

相关文章

如何把公章盖在电子档文件上?

将公章盖在电子档文件上&#xff0c;尤其是确保其法律效力和安全性&#xff0c;通常涉及以下步骤&#xff1a; 准备工作 获取合法的电子公章&#xff1a;确保你拥有公司或机构正式授权的电子公章图像&#xff0c;且该图像经过了必要的加密或数字签名处理&#xff0c;以确保其…

特征提取与深度神经网络(二)

关键点/角点检测 2011论文-ORB关键点检测&#xff0c;比SIFT与SURF速度更快。 ORB算法可以看出两个部分组成&#xff1a;快速关键点定位BRIEF描述子生成 Fast关键点检测&#xff1a; 选择当前像素点P&#xff0c;阈值T&#xff0c;周围16个像素点&#xff0c;超过连续N12个像素…

SparkSQL概述

1.1. SparkSQL介绍 SparkSQL&#xff0c;就是Spark生态体系中的构建在SparkCore基础之上的一个基于SQL的计算模块。SparkSQL的前身不叫SparkSQL&#xff0c;而是叫做Shark。最开始的时候底层代码优化、SQL的解析、执行引擎等等完全基于Hive&#xff0c;总是Shark的执行速度要比…

SpringCloud:认识微服务

程序员老茶 &#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;程序员老茶 &#x1f64a; P   S : 点赞是免费的&#xff0c;却可以让写博客的作者开心好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#…

让数据更「高效」一点!IvorySQL在Neon平台上的迅速部署和灵活应用

IvorySQL本身就是一个100%兼容PostgreSQL最新内核的开源数据库系统&#xff0c;而Neon Autoscaling Platform通常支持多种数据库和应用程序。将IvorySQL集成到该平台后&#xff0c;可以进一步增强与其他系统和应用程序的兼容性&#xff0c;同时更全面的体验IvorySQL的Oracle兼容…

lint 代码规范,手动修复,以及vscode的第三方插件eslint自动修复

ESlint代码规范 不是语法规范&#xff0c;是一种书写风格&#xff0c;加多少空格&#xff0c;缩进多少&#xff0c;加不加分号&#xff0c;类似于书信的写作格式 ESLint:是一个代码检查工具&#xff0c;用来检查你的代码是否符合指定的规则(你和你的团队可以自行约定一套规则)…

【3dmax笔记】032: 编辑顶点

一、编辑顶点概述 (1)启动安装好的3dmax软件。 (2)选择顶视图,用图形画出一个矩形。 (3)选择矩形,右击鼠标,将矩形转换成可编辑样条线。 (4)进入顶点层级。 展开可编辑样条线,选择顶点层级(快捷键为1,在不展开样条线的情况下也可以选择顶点层级)。选择后,可以…

python:做柱状图

import matplotlib.pyplot as plt # 数据 categories [A, B, C, D] values [23, 45, 56, 78] # 创建柱状图 plt.bar(categories, values) # 添加标题和标签 plt.title(柱状图示例) plt.xlabel(类别) plt.ylabel(数值) # 显示图形 plt.show() D:\software\新建文件夹\python\L…

TODESK远程开机的原理

在现代计算机技术飞速发展的背景下&#xff0c;远程控制软件成为我们日常工作中不可或缺的工具。其中&#xff0c;ToDesk作为一款高效且易用的远程控制软件&#xff0c;备受用户青睐。那么&#xff0c;ToDesk远程开机的原理是什么呢&#xff1f;本文将为你揭晓这个秘密。 KKVie…

[淘宝销量]—采集分析—实例参考▶

[干货] 本文爬取淘宝的搜索结果&#xff0c;包含标题、价格、原价、店铺、月销量字段。将结果保存成csv格式&#xff0c;并作简单分析。以手机为例。【淘宝销量】 用到的python库&#xff1a;selenium、urllib、pyquery、pandas。 1.爬取页面分析 1.1 获取URL 打开淘宝&am…

Python | Leetcode Python题解之第79题单词搜索

题目&#xff1a; 题解&#xff1a; class Solution:def exist(self, board: List[List[str]], word: str) -> bool:def dfs(i, j, k):if not 0 < i < len(board) or not 0 < j < len(board[0]) or board[i][j] ! word[k]: return Falseif k len(word) - 1: r…

Linux线程(一)初识线程

目录 一、什么是线程 二、线程和进程的区别 三、线程的操作 1、创建线程 2、获取线程ID 3、线程的终止与等待 4、线程分离 一、什么是线程 在Linux中&#xff0c;线程&#xff08;thread&#xff09;是一种轻量级进程&#xff08;Light-weight Process, LWP&#xff09…

五一超级课堂---Llama3-Tutorial(Llama 3 超级课堂)---第一节 Llama 3 本地 Web Demo 部署

课程文档&#xff1a; https://github.com/SmartFlowAI/Llama3-Tutorial 课程视频&#xff1a; https://space.bilibili.com/3546636263360696/channel/collectiondetail?sid2892740&spm_id_from333.788.0.0 操作平台&#xff1a; https://studio.intern-ai.org.cn/consol…

全面解析C++11与C++20线程(含内容)

昨晚跟一些小伙伴做了第一次直播尝试&#xff0c;一起探讨了C11 thread与 C20的jthread&#xff0c;于此同时给大家出了几个问题&#xff0c;在直播之外不会公布答案&#xff0c;所以以后直播还是得跟着走起。 总共有22人参加直播&#xff0c;氛围相当不错&#xff0c;没有录播…

Linux 无名信号量(Semaphore)的使用

目录 一、无名信号量的概念二、无名信号量相关函数三、信号量的使用步骤四、应用场景五、测试代码 一、无名信号量的概念 Linux无名信号量&#xff08;Semaphore&#xff09;   在Linux操作系统中&#xff0c;信号量&#xff08;Semaphore&#xff09;是一种用于进程间或线程…

sqlite3命令行工具无法退出问题处理

一、背景&#xff1a; 软件使用的后台数据库为sqlite&#xff0c;linux主机系统层面使用sqlite3命令行工具登录数据库后&#xff0c;无法执行sql脚本&#xff0c;无法退出sqlite3。无法执行ctrlc&#xff0c;执行ctrlz后sqlite3前台进程被中断&#xff0c;但是该进程没有退出。…

字节发布文生图模型PuLID:高效身份ID特征定制,单张图像克隆AI虚拟分身

前言 字节研究团队近日提出了一种新型的文生图身份ID定制方法PuLID(Pure and Lightning ID Customization)。相较于传统的微调方法&#xff0c;PuLID无需复杂的参数优化就可以实现高效的身份ID定制&#xff0c;且能最大程度减少对原始模型行为的干扰。 PuLID是通过将轻量级的…

docker学习-docker常用其他命令整理

随便写写&#xff0c;后面有空再更新 镜像命令&#xff0c;容器命令已在之前略有更新&#xff0c;这次不写&#xff0c; 一、后台启动命令 # 命令 docker run -d 容器名 # 例子 docker run -d centos # 启动centos&#xff0c;使用后台方式启动 # 问题&#xff1a; 使用doc…

Electron学习笔记(一)

文章目录 相关笔记笔记说明 一、轻松入门 1、搭建开发环境2、创建窗口界面3、调试主进程 二、主进程和渲染进程1、进程互访2、渲染进程访问主进程类型3、渲染进程访问主进程自定义内容4、渲染进程向主进程发送消息5、主进程向渲染进程发送消息6、多个窗口的渲染进程接收主进程发…

OSError: image file is truncated (36 bytes not processed)解决方案

错误原因&#xff1a; 图像文件被损坏 解决方案&#xff1a; 代码开头添加如下两行代码&#xff1a; from PIL import ImageFile ImageFile.LOAD_TRUNCATED_IMAGES True