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

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.rhkb.cn/news/324052.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

英语学习笔记8——What‘s your job?

What’s your job? 你是做什么工作的&#xff1f; 词汇 Vocabulary policeman 男警察 policewoman 女警察 police n. 警力 集合名词&#xff0c;永表复数 西方国家警察管的事很多。交警&#xff0c;刑警&#xff0c;武警一般不分开。 taxi driver 出租车司机 taxi / cab n.…

Unity3D DOTween

简单介绍一下 DOTween 插件的使用。 导入插件 先到 Asset Store 获取 DOTween 插件&#xff0c;然后在 Package Manager 的 My Assets 中搜索&#xff0c;下载并导入插件。 导入后&#xff0c;会自动弹出一个窗口&#xff0c;提示需要先对插件进行配置。 点击上图中的按钮&am…

Linux:进程通信(三)信号的捕捉

目录 一、信号捕捉函数 1、signal函数 2、sigaction函数 二、用户态与内核态 1、用户态 2、内核态 用户态与内核态转换 三、volatile关键字 四、SIGCHLD信号 一、信号捕捉函数 1、signal函数 signal函数是C语言标准库中的一个函数&#xff0c;用于处理Unix/Linux系…

RK3568 学习笔记 : 精简 u-boot env 默认复杂的多种引导启动设置

前言 环境&#xff1a; 正点原子 Atompi-CA1 RK3568 开发板、正点原子 DLRK3568 开发板&#xff0c;&#xff08;一时脑热买了两块 RK3568 开发板&#xff09;&#xff0c;Atompi-CA1 RK3568 开发板比较小巧&#xff0c;利于一些前期的嵌入式 Linux 开发学习与实践。 RK3568 开…

Android 11 输入系统之InputDispatcher和应用窗口建立联系

InputDispatcher把输入事件传给应用之前&#xff0c;需要和应用窗口建立联系&#xff0c;了解了这个过程&#xff0c;就清楚了APP进程和InputDispatcher线程也就是SystemServer进程之间是如何传输数据了 我们向窗口addView的时候&#xff0c;都会调用到ViewRootImpl的setView方…

热爱电子值得做的电子制作实验

加我zkhengyang&#xff0c;进嵌入式音频系统研究开发交流答疑群(课题组) AM/FM收音机散件制作&#xff0c;磁带随声听散件&#xff0c;黑白电视机散件制作&#xff0c;功放散件制作&#xff0c;闪光灯散件制作&#xff0c;声控灯散件&#xff0c;等等&#xff0c;可提高动手能…

kali linux更新卡在libc6:amd64 (2.37-15)

适配于linux的windows子系统&#xff0c;wsl2&#xff0c;安装kali linux&#xff0c;运行 sudo apt update 卡在&#xff1a;Setting up libc6:amd64 (2.37-15) … 关机重启、重新修复执行也不行 解决办法&#xff1a;kill当前apt进程或者关机重启kali-linux&#xff0c;然…

【Linux】学习笔记

文章目录 [toc]第一章&#xff1a;基础篇01|课程介绍02|内容综述03|什么是Linux04|Linux的内核版本及常见发行版内核版本发行版本Red Hat Enterprise LinuxFedoraCentOSDebianUbuntu 05|安装VirtualBox虚拟机VirtualBox下载url 06|在虚拟机中安装Linux系统Linux安装镜像下载 07…

SpringBoot+vue实现右侧登录昵称展示

目录 1. 定义User数据 1.1.在created方法获取数据 1.2.头部导航栏绑定User数据 1.3.在data中定义User数据 2. 获取数据 2.1.接收父组件传递的值 2.2.展示数据 3. 页面效果 在SpringBoot和 Vue.js 结合的项目中实现右侧登录昵称展示&#xff0c;通常涉及到前端的用户界面…

ROS机器人入门:机器人系统仿真【学习记录】——2

承接上一篇博客&#xff1a; ROS机器人入门&#xff1a;机器人系统仿真【学习记录】——1-CSDN博客 我们先前结束了&#xff08;上一篇博客中&#xff09;&#xff1a; 1. 概述 2. URDF集成Rviz基本流程 3. URDF语法详解 4. URDF优化_xacro 下面让我们继续学习ROS机器人…

会话劫持攻击就在我们身边,我们要如何防范

会话劫持攻击&#xff08;Session Hijacking&#xff09;是一种网络攻击方式&#xff0c;攻击者通过某种手段获取到用户的会话标识&#xff08;Session ID&#xff09;&#xff0c;然后使用这个会话标识冒充合法用户进行恶意操作。这种攻击方式允许攻击者以合法用户的身份访问受…

FFmpeg常用命令详解与实战指南

下载地址&#xff1a;Releases BtbN/FFmpeg-Builds (github.com) 1. 获取视频信息 使用FFmpeg获取视频信息是最基本的操作之一。你可以使用-i选项指定输入文件&#xff0c;然后使用FFmpeg内置的分析器来获取视频的各种信息&#xff0c;包括视频编解码器、音频编解码器、分辨…

《Mask2Former》算法详解

文章地址&#xff1a;《Masked-attention Mask Transformer for Universal Image Segmentation》 代码地址&#xff1a;https://github.com/facebookresearch/Mask2Former 文章为发表在CVPR2022的一篇文章。从名字可以看出文章像提出一个可以统一处理各种分割任务&#xff08;…

智慧公厕,运用数据提升公共厕所管理水平!

随着城市人口的增加和生活水平的提高&#xff0c;公共厕所的管理变得越来越重要。传统的厕所管理方式已经无法满足人们对卫生、便利和舒适的需求。而智慧公厕作为新一代公厕管理方式&#xff0c;通过运用数据技术和大数据分析手段&#xff0c;彻底改变了公厕管理的模式&#xf…

远程桌面连接不上怎么连服务器,原因是什么?如何解决?

远程桌面连接不上怎么连服务器&#xff0c;原因是什么&#xff1f;如何解决&#xff1f; 面对远程桌面连接不上的困境&#xff0c;我们有办法&#xff01; 当你尝试通过远程桌面连接服务器&#xff0c;但遭遇连接失败的挫折时&#xff0c;不要慌张。这种情况可能由多种原因引起…

26、Qt使用QFontDatabase类加载ttf文件更改图标颜色

一、图标下载 iconfont-阿里巴巴矢量图标库 点击上面的链接&#xff0c;在打开的网页中搜索自己要使用的图标&#xff0c;如&#xff1a;最大化 找到一个自己想用图标&#xff0c;选择“添加入库” 点击“购物车”图标 能看到刚才添加的图标&#xff0c;点击“下载代码”(需要…

4D 成像毫米波雷达:新型传感器助力自动驾驶

1 感知是自动驾驶的首要环节&#xff0c;高性能传感器必不可少 感知环节负责对侦测、识别、跟踪目标&#xff0c;是自动驾驶实现的第一步。自动驾驶的实现&#xff0c;首先要能够准确理解驾驶环境信息&#xff0c;需要对交通主体、交通信号、环境物体等信息进行有效捕捉&#x…

数据可视化训练第二天(对比Python与numpy中的ndarray的效率并且可视化表示)

绪论 千里之行始于足下&#xff1b;继续坚持 1.对比Python和numpy的性能 使用魔法指令%timeit进行对比 需求&#xff1a; 实现两个数组的加法数组 A 是 0 到 N-1 数字的平方数组 B 是 0 到 N-1 数字的立方 import numpy as np def numpy_sum(text_num):"""…

一起深度学习(AlexNet网络)

AlexNet神经网络 代码实现&#xff1a; 代码实现&#xff1a; import torch from torch import nn from d2l import torch as d2lnet nn.Sequential(# 采用了11*11的卷积核来捕捉对象&#xff0c;因为原始输入数据比较大#步幅为4 &#xff0c;可减少输出的高度核宽度。#输出通…

全栈开发之路——前端篇(6)生命周期和自定义hooks

全栈开发一条龙——前端篇 第一篇&#xff1a;框架确定、ide设置与项目创建 第二篇&#xff1a;介绍项目文件意义、组件结构与导入以及setup的引入。 第三篇&#xff1a;setup语法&#xff0c;设置响应式数据。 第四篇&#xff1a;数据绑定、计算属性和watch监视 第五篇 : 组件…