【C++算法】49.分治_归并_计算右侧小于当前元素的个数

文章目录

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


题目链接:

315. 计算右侧小于当前元素的个数


题目描述:

43a7095d3fe51d805abbf5facf494e6c


解法

归并排序(分治)

当前元素的后面,有多少个比我小。(降序)

6a04400aebd905e678bac21f1ccb26b7


C++ 算法代码:

class Solution 
{vector<int> ret;        // 存储结果:每个元素右侧小于当前元素的个数vector<int> index;      // 记录 nums 中当前元素的原始下标,用于追踪元素位置int tmpNums[500010];    // 临时数组,用于归并排序中合并两个子数组int tmpIndex[500010];   // 临时数组,用于保存合并后的索引顺序
public:vector<int> countSmaller(vector<int>& nums) {int n = nums.size();ret.resize(n);      // 初始化结果数组大小,默认值都是0index.resize(n);    // 初始化索引数组大小// 初始化索引数组,记录每个元素的原始位置for(int i = 0; i < n; i++)index[i] = i;mergeSort(nums, 0, n - 1);  // 对整个数组进行归并排序return ret;  // 返回结果数组}void mergeSort(vector<int>& nums, int left, int right){if(left >= right) return;  // 基本情况:如果区间只有一个元素或为空,则直接返回// 1. 根据中间元素,划分区间int mid = (left + right) >> 1;  // 计算中间位置,相当于 (left + right) / 2// 2. 递归地处理左右两部分mergeSort(nums, left, mid);       // 排序左半部分mergeSort(nums, mid + 1, right);  // 排序右半部分// 3. 合并两个有序子数组,同时计算右侧小于当前元素的个数int cur1 = left, cur2 = mid + 1, i = 0;  // cur1指向左子数组,cur2指向右子数组,i遍历辅助数组while(cur1 <= mid && cur2 <= right)  // 当两个子数组都还有元素时{if(nums[cur1] <= nums[cur2])  // 如果左子数组当前元素小于等于右子数组当前元素{tmpNums[i] = nums[cur2];       // 将右子数组的元素放入临时数组tmpIndex[i++] = index[cur2++]; // 同时记录对应的原始索引}else  // 如果左子数组当前元素大于右子数组当前元素{// 核心逻辑:此时右子数组中从cur2到right的所有元素都小于当前的nums[cur1]ret[index[cur1]] += right - cur2 + 1;  // 将这些元素的数量累加到结果中tmpNums[i] = nums[cur1];       // 将左子数组的元素放入临时数组tmpIndex[i++] = index[cur1++]; // 同时记录对应的原始索引}}// 4. 处理剩余元素while(cur1 <= mid)  // 处理左子数组中剩余的元素{tmpNums[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}while(cur2 <= right)  // 处理右子数组中剩余的元素{tmpNums[i] = nums[cur2];tmpIndex[i++] = index[cur2++];}// 5. 将临时数组中的元素复制回原数组for(int j = left; j <= right; j++){nums[j] = tmpNums[j - left];    // 更新原数组中的元素值index[j] = tmpIndex[j - left];  // 更新原数组中元素对应的原始索引}}
};

图解

例如:nums = [5, 2, 6, 1]

  1. 初始化:

    • ret = [0, 0, 0, 0] (结果数组,初始全为0)

    • index = [0, 1, 2, 3] (原始索引数组)

  2. 第一次划分:

    • [5, 2, 6, 1] 分为 [5, 2][6, 1]
  3. 处理左半部分 [5, 2]:

    • 进一步划分为 [5][2]

    • 这些是单个元素,不再划分

    • 合并 [5][2] (降序合并):

      • 比较 5 和 2,5 > 2,nums[cur1] > nums[cur2]
      • ret[index[cur1]] += right - cur2 + 1;
      • 因为左边元素大,所以选择左边元素,ret 不变
      • 合并后,左半部分变为 [5, 2],索引变为 [0, 1]
  4. 处理右半部分 [6, 1]:

    • 进一步划分为 [6][1]

    • 这些是单个元素,不再划分

    • 合并 [6][1] (降序合并):

      • 比较 6 和 1,6 > 1
      • 因为左边元素大,所以选择左边元素,ret 不变
      • 合并后,右半部分变为 [6, 1],索引变为 [2, 3]
  5. 最后合并[5, 2][6, 1] (降序合并):

    • 比较 5 和 6: 5 <= 6,选择右侧元素6,ret 不变
    • 比较 5 和 1: 5 > 1,这时右子数组中只有1比5小,所以ret[index[cur1]] += right - cur2 + 1 → ret[0] += 3 - 3 + 1 → ret[0] = 1
    • 比较 2 和 1: 2 > 1,右子数组中只有1比2小,所以 ret[index[cur1]] += right - cur2 + 1 →ret[1] += 3 - 3 + 1 → ret[1] = 1
  6. 最终结果:

    • ret = [2, 1, 1, 0]

cc1bbde68ae421a0abb80e937adf99dd

dd78a1d53f223fd68ed1645ec085b2c5

3.第一次循环:while(cur1 <= mid && cur2 <= right)

cc777c3fb975c9588349d54785bb13e9

4.第二次循环:while(cur1 <= mid && cur2 <= right)

5db771f1da7e5699c902ef1ac77cd8d7

5.第三次循环:while(cur1 <= mid && cur2 <= right)

76e3aa9d564889b57ce5a93b5886d9df

6.处理剩余元素while(cur2 <= right)

5b9a2a1570bbcb541b530e188715fa2c

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

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

相关文章

IPSec简单例子

实验说明 使用Ensp模拟器实现IPsec隧道实验。IPSec是一种VPN技术&#xff0c;配置的思路首先是两个网络先通&#xff0c;然后配置ACL、IEK和IPSec对等体&#xff0c;从而建立VPN隧道。 实验拓扑 配置过程 1 配置IP地址以及OSPF路由 # 配置中使用了简写命令&#xff0c;不熟…

车载联网终端4G汽车TBOX介绍定义与概述

汽车 TBOX&#xff08;Telematics Box&#xff09;是专为汽车设计的远程通信终端设备&#xff0c;属于车联网系统的关键组成部分。车联网系统一般包含主机、汽车 T - BOX、手机 APP 及后台系统。融合了车身网络和 4G 无线通信技术&#xff0c;为汽车提供丰富的 Telematics 服务…

《DeepSeek RAG 增强检索知识库系统》Ollama DeepSeek 流式应答页面对接之三

前言 自从有了 AI 工具以后&#xff0c;所有以前头疼前端页面开发的后端程序员&#x1f468;&#x1f3fb;‍&#x1f4bb;&#xff0c;都漏出了友善&#x1f60a;微笑&#xff01; 主要我们可以清楚地表达编写页面诉求&#xff0c;AI 工具就可以非常准确且迅速的完成代码的实…

【MyBatis】深入解析 MyBatis:关于注解和 XML 的 MyBatis 开发方案下字段名不一致的的查询映射解决方案

注解查询映射 我们再来调用下面的 selectAll() 这个接口&#xff0c;执行的 SQL 是 select* from user_info&#xff0c;表示全列查询&#xff1a; 运行测试类对应方法&#xff0c;在日志中可以看到&#xff0c;字段名一致&#xff0c;Mybatis 就成功从数据库对应的字段中拿到…

深入理解Java性能调优与JVM底层机制

Java作为一种广泛应用的编程语言&#xff0c;在企业级应用中占据着举足轻重的地位。随着系统规模的扩大和业务需求的复杂化&#xff0c;性能调优成为了开发过程中不可忽视的一环。Java的性能瓶颈往往并不直接来自代码本身&#xff0c;而是与JVM&#xff08;Java虚拟机&#xff…

odo18实施——销售-仓库-采购-制造-制造外包-整个流程自动化单据功能的演示教程

安装模块 安装销售 、库存、采购、制造模块 2.开启外包功能 在进入制造应用点击 配置—>设置 勾选外包&#xff0c;点击保存 添加信息 一、添加客户信息 点击到销售应用 点击订单—>客户 点击新建 创建客户1&#xff0c;及其他客户相关信息&#xff0c;点…

Logo语言的在线课程学习

Logo语言在线课程学习的探索 引言 在信息技术快速发展的今天&#xff0c;编程已经成为一门重要的技能。尤其随着人工智能、数据分析和互联网技术的普及&#xff0c;各种编程语言层出不穷&#xff0c;其中Logo语言以其独特的教育意义和学习优势&#xff0c;逐渐受到学校和教育…

情感语音的“开源先锋”!网易开源

语音合成技术近年来取得了显著进步&#xff0c;特别是在语音克隆、语音助手、配音服务和有声读物等领域。然而&#xff0c;如何让合成的语音更具情感&#xff0c;更贴近人类的真实表达&#xff0c;一直是这一领域的重要研究方向。今天&#xff0c;我们将为大家介绍一款由网易有…

摄像头模块对焦方式的类型

摄像头模块的对焦方式直接影响成像清晰度和使用场景适应性&#xff0c;不同技术各有其优缺点。以下是常见对焦方式及其原理、特点和应用场景的详细说明&#xff1a; ‌1. 固定对焦&#xff08;Fixed Focus&#xff09;‌ ‌原理‌&#xff1a;镜头固定在特定距离&#xff08;…

使用Vue、Nodejs以及websocket搭建一个简易聊天室

简易聊天室 说在前面效果展示websocketwebsocket的由来websocket的特点 vue前端静态结构效果代码 点击切换用户以及该用户高亮实现思路效果展示 发送消息功能效果展示 连接服务端 Nodejs服务器端实现步骤代码 说在前面 在学习计算机网络的时候&#xff0c;看到了websocket这个…

【免费】2005-2019年各地级市绿色专利申请量数据

2005-2019年各地级市绿色专利申请量数据 1、时间2005-2019年 2、来源&#xff1a;国家知识产权局 3、指标&#xff1a;省份、城市、年份、绿色发明专利申请量、绿色实用新型专利申请量 4、范围&#xff1a;360地级市 5、指标解释&#xff1a;绿色专利是指涉及环保、新能源…

架构师面试(二十六):系统拆分

问题 今天我们聊电商系统实际业务场景的问题&#xff0c;考查对业务系统问题的分析能力、解决问题的能力和对系统长期发展的整体规划能力。 一电商平台在早期阶段业务发展迅速&#xff0c;DAU在 10W&#xff1b;整个电商系统按水平分层架构进行设计&#xff0c;包括【入口网关…

2. Qt界面文件原理

本节主要介绍ui文件如何与窗口关联&#xff0c;并通过隐式连接方式显示对话框 本文部分ppt、视频截图原链接&#xff1a;[萌马工作室的个人空间-萌马工作室个人主页-哔哩哔哩视频] 1 UI文件如何与窗口关联 1.1 mainwindow.cpp的头文件ui_mainwindow.h 根据编译原理的基本规…

雅思大作文写作——词伙、简单句、并列句的使用

词伙是一些可以表达我们常用观点的单词组合,这个组合可能不只是2-3个单词,也可能是很多单词组成的一个短句。 一、词伙使用 1. 不要中译英 2. 重视词伙,而非单词 如何替换表达 1. 如果要替换的是一个名词,如students,则有下面的一些方法: A. 使用替换词或者词组:y…

⭐算法OJ⭐滑动窗口最大值【双端队列(deque)】Sliding Window Maximum

文章目录 双端队列(deque)详解基本特性常用操作1. 构造和初始化2. 元素访问3. 修改操作4. 容量操作 性能特点时间复杂度&#xff1a;空间复杂度&#xff1a; 滑动窗口最大值题目描述方法思路解决代码 双端队列(deque)详解 双端队列(deque&#xff0c;全称double-ended queue)是…

电机的了解到调试全方面讲解

一、什么是电机 电机是一种将电能转换为机械能的装置,通常由定子、转子和电磁场组成。 当电流通过电机的绕组时,产生的磁场会与电机中的磁场相互作用,从而使电机产生旋转运动。电机广泛应用于各种机械设备和工业生产中,是现代社会不可或缺的重要设备之一。 常见的电机种…

分布式微服务系统架构第97集:JVM底层原理

加群联系作者vx&#xff1a;xiaoda0423 仓库地址&#xff1a;https://webvueblog.github.io/JavaPlusDoc/ https://1024bat.cn/ JVM 内存结构 Java 虚拟机的内存空间分为 5 个部分&#xff1a; 程序计数器 Java 虚拟机栈 本地方法栈 堆 方法区 JDK 1.8 同 JDK 1.7 比&…

制定大运维管理体系的标准、流程、机制、规范

规划并制定大运维管理体系的标准、流程、机制、规范&#xff0c;对于确保平台的可用性和稳定性至关重要。这一过程涉及从顶层设计到具体执行的全面考量&#xff0c;需要综合考虑业务需求、技术架构、团队能力等多方面因素。以下是一个基本框架&#xff0c;用于指导如何构建有效…

TruPlasma RF 3006 软件TRUMPF HUETTINGER TRUPLASMA RF 3006 调试监控软件

TruPlasma RF 3006 软件TRUMPF HUETTINGER TRUPLASMA RF 3006 调试监控软件

第16届蓝桥杯单片机模拟试题Ⅱ

试题 代码 sys.h #ifndef __SYS_H__ #define __SYS_H__#include <STC15F2K60S2.H> //ds1302.c extern unsigned char time[3]; void w_ds1302(); void r_ds1302(); //iic.c float v_adc(unsigned char addr); //sys.c extern float light_v; extern float rb2_v; exte…