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

【C++算法】50.分治_归并_翻转对

文章目录

    • 题目链接:
    • 题目描述:
    • 解法
    • C++ 算法代码:
    • 图解


题目链接:

493. 翻转对


题目描述:

e1a56c57c284100520d1840d3224460e


解法

分治

策略一:计算当前元素cur1后面,有多少元素的两倍比我cur1小(降序)

利用单调性使用同向双指针。

6ca12f25aadf9a660c566e1254f800d0

策略二:计算当前元素cur2之前,有多少元素的一半比我cur2大(升序)

8ae918bf3c685ed0b37605b78c2cc096

最后合并两个有序数组。


C++ 算法代码:

降序版本

class Solution 
{int tmp[50010];  // 临时数组,用于归并排序中合并两个子数组
public:// 主函数,计算数组中的翻转对数量int reversePairs(vector<int>& nums) {return mergeSort(nums, 0, nums.size() - 1);  // 调用归并排序函数}// 归并排序函数,返回区间[left, right]内的翻转对数量int mergeSort(vector<int>& nums, int left, int right){if(left >= right) return 0;  // 基本情况:如果区间只有一个元素或为空,翻转对数量为0int ret = 0;  // 保存翻转对数量// 1. 先根据中间元素划分区间int mid = (left + right) >> 1;  // 计算中间位置,相当于 (left + right) / 2// 2. 递归计算左右两侧的翻转对数量ret += mergeSort(nums, left, mid);       // 左半部分翻转对数量ret += mergeSort(nums, mid + 1, right);  // 右半部分翻转对数量// 3. 计算跨越左右两个子数组的翻转对数量int cur1 = left, cur2 = mid + 1;// 对于左子数组中的每个元素,计算右子数组中有多少元素可以构成翻转对while(cur1 <= mid) {// 在右子数组中查找第一个小于 nums[cur1]/2 的元素位置// 即满足 nums[cur2] < nums[cur1]/2 的最小的cur2while(cur2 <= right && nums[cur2] >= nums[cur1] / 2.0) cur2++;if(cur2 > right)  // 如果右子数组中所有元素都不满足条件break;// 右子数组中从cur2到right的所有元素都能与nums[cur1]构成翻转对ret += right - cur2 + 1;cur1++;  // 处理左子数组中的下一个元素}// 4. 合并两个有序子数组(降序合并)cur1 = left;cur2 = mid + 1;int i = left;  // 临时数组的起始索引// 比较左右子数组元素,较大者先放入临时数组while(cur1 <= mid && cur2 <= right)tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur2++] : nums[cur1++];// 处理剩余元素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];return ret;  // 返回翻转对总数}
};

升序版本

class Solution 
{int tmp[50010];  // 临时数组,用于归并排序中合并两个子数组
public:// 主函数,计算数组中的翻转对数量int reversePairs(vector<int>& nums) {return mergeSort(nums, 0, nums.size() - 1);  // 调用归并排序函数}// 归并排序函数,返回区间[left, right]内的翻转对数量int mergeSort(vector<int>& nums, int left, int right){if(left >= right) return 0;  // 基本情况:如果区间只有一个元素或为空,翻转对数量为0int ret = 0;  // 保存翻转对数量// 1. 先根据中间元素划分区间int mid = (left + right) >> 1;  // 计算中间位置,相当于 (left + right) / 2// 2. 递归计算左右两侧的翻转对数量ret += mergeSort(nums, left, mid);       // 左半部分翻转对数量ret += mergeSort(nums, mid + 1, right);  // 右半部分翻转对数量// 3. 计算跨越左右两个子数组的翻转对数量int cur1 = left, cur2 = mid + 1;// 对于右子数组中的每个元素,计算左子数组中有多少元素可以构成翻转对while(cur2 <= right) {// 在左子数组中查找第一个大于 2*nums[cur2] 的元素位置// 即满足 nums[cur1] > 2*nums[cur2] 的最小的cur1while(cur1 <= mid && nums[cur2] >= nums[cur1] / 2.0) cur1++;if(cur1 > mid)  // 如果左子数组中所有元素都不满足条件break;// 左子数组中从cur1到mid的所有元素都能与nums[cur2]构成翻转对ret += mid - cur1 + 1;cur2++;  // 处理右子数组中的下一个元素}// 4. 合并两个有序子数组(升序合并)cur1 = left;cur2 = mid + 1;int i = left;  // 临时数组的起始索引// 比较左右子数组元素,较小者先放入临时数组while(cur1 <= mid && cur2 <= right)tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] : 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];return ret;  // 返回翻转对总数}
};

图解

例如:nums = [1, 3, 2, 3, 1]

初始化:

  • 原始数组: [1, 3, 2, 3, 1]
  • 我们需要找到所有满足 i < jnums[i] > 2 * nums[j] 的索引对 (i, j)

第一层递归(整个数组):

  • [1, 3, 2, 3, 1] 分为 [1, 3][2, 3, 1]

处理左半部分 [1, 3]:

  • 进一步划分为 [1][3]
  • 这些是单个元素,不需要计算内部的翻转对
  • 计算跨越的翻转对: 没有跨越的翻转对(因为两个子数组只有一个元素)
  • 合并: [3, 1] (降序排序)

处理右半部分 [2, 3, 1]:

  • 进一步划分为 [2][3, 1]
  • 对于 [3, 1], 递归处理:
    • 划分为 [3][1]
    • 计算跨越的翻转对: 3 > 2*1, 所以有1个翻转对
    • 合并: [3, 1] (降序排序)
  • 计算跨越的翻转对([2] 和 [3, 1]):
    • 对于左子数组的元素2:
      • 检查右子数组的元素: 2 不大于 2*3, 但2 > 2*1
      • 所以有1个翻转对
  • 合并: [3, 2, 1] (降序排序)

最后合并 [3, 1][3, 2, 1]:

  • 计算跨越的翻转对:
    • 对于左子数组的元素3:
      • 检查右子数组的元素: 3 不大于 2*3, 3 不大于 2*2, 但3 > 2*1
      • 所以有1个翻转对
    • 对于左子数组的元素1:
      • 检查右子数组的元素: 1 不大于 2*3, 1 不大于 2*2, 1 不大于 2*1
      • 所以没有翻转对
  • 合并: [3, 3, 2, 1, 1] (降序排序)

计算翻转对总数:

  • 左半部分内部: 0个
  • 右半部分内部: 1+1=2个
  • 跨越左右半部分: 0个

因此,翻转对总数是 0 + 2 + 0 = 2 个。

这两个翻转对分别对应原数组中的:

  1. (1, 4): 索引1处的元素3 > 2*索引4处的元素1
  2. (3, 4): 索引3处的元素3 > 2*索引4处的元素1

相关文章:

【C++算法】50.分治_归并_翻转对

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a;图解 题目链接&#xff1a; 493. 翻转对 题目描述&#xff1a; 解法 分治 策略一&#xff1a;计算当前元素cur1后面&#xff0c;有多少元素的两倍比我cur1小&#xff08;降序&#xff09; 利用单…...

Github最新AI工具汇总2025年4月份第2周

根据GitHub官方动态及开发者生态最新进展&#xff0c;以下是2025年4月第二周&#xff08;截至4月7日&#xff09;值得关注的AI工具与技术更新汇总&#xff1a; 1. GitHub Copilot Agent Mode全量发布 核心功能&#xff1a;在VS Code中启用Agent模式后&#xff0c;Copilot可自主…...

用VAE作为标题显示标题过短,所以标题变成了这样

VAE (Variational Autoencoder / 变分自编码器) 基本概念: VAE 是一种生成模型 (Generative Model)&#xff0c;属于自编码器 (Autoencoder) 家族。 它的目标是学习数据的潜在表示 (Latent Representation)&#xff0c;并利用这个表示来生成新的、与原始数据相似的数据。 与标…...

docker的run命令 笔记250406

docker的run命令 笔记250406 Docker 的 run 命令用于创建并启动一个新的容器。它是 Docker 中最常用的命令之一&#xff0c;基本语法为&#xff1a; docker run [OPTIONS] IMAGE [COMMAND] [ARG...]常用选项&#xff08;OPTIONS&#xff09; 参数说明-d 或 --detach后台运行…...

基于pycatia的CATIA层级式BOM生成器开发全解析

引言:BOM生成技术的革新之路 在高端装备制造领域,CATIA的BOM管理直接影响着研发效率和成本控制。传统VBA方案 虽能实现基础功能,但存在代码维护困难、跨版本兼容性差等痛点。本文基于pycatia框架,提出一种支持动态层级识别、智能查重、Excel联动的BOM生成方案,其核心突破…...

Flink 1.20 Kafka Connector:新旧 API 深度解析与迁移指南

Flink Kafka Connector 新旧 API 深度解析与迁移指南 一、Flink Kafka Connector 演进背景 Apache Flink 作为实时计算领域的标杆框架&#xff0c;其 Kafka 连接器的迭代始终围绕性能优化、语义增强和API 统一展开。Flink 1.20 版本将彻底弃用基于 FlinkKafkaConsumer/FlinkK…...

2025年渗透测试面试题总结- 某四字大厂面试复盘扩展 一面(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 某四字大厂面试复盘扩展 一面 一、Java内存马原理与查杀 二、冰蝎与哥斯拉原理对比&#xff08;技术演…...

批量压缩 jpg/png 等格式照片|批量调整图片的宽高尺寸

图片格式种类非常的多&#xff0c;并且不同的图片由于像素、尺寸不一样&#xff0c;可能占用的空间也会不一样。文件太大会占用较多的磁盘空间&#xff0c;传输及上传系统都非常不方便&#xff0c;可能会收到限制&#xff0c;因此我们经常会碰到需要对图片进行压缩的需求。如何…...

目录穿越 + pickle反序列化 -- xyctf Signin WP

源代码 # -*- encoding: utf-8 -*-File : main.py Time : 2025/03/28 22:20:49 Author : LamentXUflag in /flag_{uuid4}from bottle import Bottle, request, response, redirect, static_file, run, route secret aapp Bottle() route(/) def index():return…...

Spring Boot 框架注解:@ConfigurationProperties

ConfigurationProperties(prefix "sky.jwt") 是 Spring Boot 框架里的一个注解&#xff0c;其主要功能是把配置文件&#xff08;像 application.properties 或者 application.yml&#xff09;里的属性值绑定到一个 Java 类的字段上。下面详细阐述其作用&#xff1a;…...

【动手学深度学习】卷积神经网络(CNN)入门

【动手学深度学习】卷积神经网络&#xff08;CNN&#xff09;入门 1&#xff0c;卷积神经网络简介2&#xff0c;卷积层2.1&#xff0c;互相关运算原理2.2&#xff0c;互相关运算实现2.3&#xff0c;实现卷积层 3&#xff0c;卷积层的简单应用&#xff1a;边缘检测3.1&#xff0…...

在huggingface上制作小demo

在huggingface上制作小demo 今天好兄弟让我帮他搞一个模型&#xff0c;他有小样本的化学数据&#xff0c;想让我根据这些数据训练一个小模型&#xff0c;他想用这个模型预测一些值 最终我简单训练了一个小模型&#xff0c;起初想把这个模型和GUI界面打包成exe发给他&#xff0…...

集合学习内容总结

集合简介 1、Scala 的集合有三大类&#xff1a;序列 Seq、集Set、映射 Map&#xff0c;所有的集合都扩展自 Iterable 特质。 2、对于几乎所有的集合类&#xff0c;Scala 都同时提供了可变和不可变的版本&#xff0c;分别位于以下两个包 不可变集合&#xff1a;scala.collect…...

51.评论日记

千万不能再挖了&#xff0c;否则整个华夏文明将被改写。_哔哩哔哩_bilibili 2025年4月7日22:13:42...

SpringCloud第二篇:注册中心Eureka

注册中心的意义 注册中心 管理各种服务功能包括服务的注册、发现、熔断、负载、降级等&#xff0c;比如dubbo admin后台的各种功能。 有了注册中心&#xff0c;调用关系的变化&#xff0c;画几个简图来看一下。(了解源码可求求: 1791743380) 服务A调用服务B 有了注册中心之后&a…...

ES 参数调优

1、refresh_interval 控制索引刷新的时间间隔。增大这个值可以减少I/O操作&#xff0c;从而提升写入性能&#xff0c;但会延迟新文档的可见性 查看 GET /content_erp_nlp_help_202503191453/_settings?include_defaultstrue 动态修改&#xff1a;refresh_interval 是一个动态…...

用claude3.7,不到1天写了一个工具小程序(11个工具6个游戏)

一、功能概览和本文核心 本次开发&#xff0c;不是1天干撸&#xff0c;而是在下班后或早起搞的&#xff0c;总体加和计算了一下&#xff0c;大概1天的时间&#xff08;12个小时&#xff09;&#xff0c;平常下班都是9点的衰仔&#xff0c;好在还有双休&#xff0c;谢天谢地。 …...

【GeoDa使用】空间自相关分析操作

使用 GeoDa 软件进行空间自相关分析 双击打开 GeoDa 软件 选择 .shp 文件 导入文件 空间权重矩阵&#xff08;*.gal / *.gwt&#xff09;是进行任何空间分析的前提 构建空间权重矩阵 空间权重矩阵&#xff08;Spatial Weights Matrix&#xff09; 是一个用来描述空间对象之间…...

什么是数据

一、数据的本质定义​​ ​​哲学视角​​ 亚里士多德《形而上学》中"未加工的观察记录"现代认知科学&#xff1a;人类感知系统接收的原始刺激信号&#xff08;如视网膜光信号、听觉神经电信号&#xff09;信息论奠基人香农&#xff1a;消除不确定性的度量载体 ​​…...

C++基于rapidjson的Json与结构体互相转换

简介 使用rapidjson库进行封装&#xff0c;实现了使用C对结构体数据和json字符串进行互相转换的功能。最短只需要使用两行代码即可无痛完成结构体数据转换为Json字符串。 支持std::string、数组、POD数据&#xff08;int,float,double等&#xff09;、std::vector、嵌套结构体…...

OpenStack Yoga版安装笔记(十七)安全组笔记

一、安全组与iptables的关系 OpenStack的安全组&#xff08;Security Group&#xff09;默认是通过Linux的iptables实现的。以下是其主要实现原理和机制&#xff1a; 安全组与iptables的关系 OpenStack的安全组规则通过iptables的规则链实现。每条安全组规则会被转换为相应的i…...

通义万相2.1 图生视频:为AI绘梦插上翅膀,开启ALGC算力领域新纪元

通义万相2.1图生视频大模型 通义万相2.1图生视频技术架构万相2.1的功能特点性能优势与其他工具的集成方案 蓝耘平台部署万相2.1核心目标典型应用场景未来发展方向 通义万相2.1ALGC实战应用操作说明功能测试 为什么选择蓝耘智算蓝耘智算平台的优势如何通过API调用万相2.1 写在最…...

Debezium日常分享系列之:Debezium3.1版本之增量快照

Debezium日常分享系列之&#xff1a;Debezium3.1版本之增量快照 按需快照触发一次临时增量快照触发临时阻塞快照增量快照增量快照过程如何 Debezium 解决具有相同主键的记录之间的冲突快照窗口触发增量快照使用附加条件运行临时增量快照使用 Kafka 信号通道触发增量快照临时增量…...

聊聊Spring AI的RedisVectorStore

序 本文主要研究一下Spring AI的RedisVectorStore 示例 pom.xml <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-vector-store-redis</artifactId> </dependency>配置 spring:ai:vectorstore:…...

Diffusion Policy Visuomotor Policy Learning via Action Diffusion官方项目解读(二)(4)

运行官方代码库中提供的Colab代码&#xff1a;vision-based environment&#xff08;二&#xff09;&#xff08;4&#xff09; 十六、函数unnormalize_data&#xff0c;继承自torch.utils.data.Dataset十六.1 def __init__()十六.2 def __len__ ()十六.3 def __getitem__()总体…...

52.个人健康管理系统小程序(基于springbootvue)

目录 1.系统的受众说明 2.开发环境与技术 2.1 MYSQL数据库 2.2 Java语言 2.3 微信小程序技术 2.4 SpringBoot框架 2.5 B/S架构 2.6 Tomcat 介绍 2.7 HTML简介 2.8 MyEclipse开发工具 3.系统分析 3.1 可行性分析 3.1.1 技术可行性 3.1.2 经济可行性 3.1.3 操作…...

学习比较JVM篇(六):解读GC日志

一、前言 在之前的文章中&#xff0c;我们对JVM的结构、垃圾回收算法、垃圾回收器做了一些列的讲解&#xff0c;同时也使用了JVM自带的命令行工具进行了实际操作。今天我们继续讲解JVM。 我们学习JVM的目的是为了了解JVM&#xff0c;然后优化对应的参数。那么如何了解JVM运行…...

I²S协议概述与信号线说明

IIS协议概述 ​ IS&#xff08;Inter-IC Sound&#xff09;协议&#xff0c;又称 IIS&#xff08;Inter-IC Sound&#xff09;&#xff0c;是一种专门用于数字音频数据传输的串行总线标准&#xff0c;由飞利浦&#xff08;Philips&#xff09;公司提出。该协议通常用于微控制器…...

b4a安卓开发技术和建议,VB6开发Android APK

b4a功能建议实现方法想法创意Wait For可以在参数中直接返回结果吗&#xff1f;Wait For (cam.OpenCamera(front)) Complete (TaskIndex As Int) Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean) 函数别名&#xff0c;减少代码&#xff0c;通用函…...

计算机网络-子网划分试题七

计算机网络中IP地址为172.16.20.60、172.16.30.60、172.16.80.60&#xff0c;子网掩码为255.255.192.0的三台计算机的网络号&#xff0c;子网号及主机号&#xff0c;并确定三台计算机是否处于同一个子网&#xff0c;如果不是请指出哪些在同一个子网&#xff0c;哪些不是&#x…...