《算法题讲解指南:优选算法-分治-归并》--49.计算右侧小于当前元素的个数,50.翻转对

《算法题讲解指南:优选算法-分治-归并》--49.计算右侧小于当前元素的个数,50.翻转对

🔥小叶-duck个人主页

❄️个人专栏《Data-Structure-Learning》

《C++入门到进阶&自我学习过程记录》《算法题讲解指南》--优选算法

未择之路,不须回头
已择之路,纵是荆棘遍野,亦作花海遨游


目录

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

题目链接:

题目描述:

题目示例:

解法(归并排序):

算法思路:

C++算法代码:

算法总结及流程解析:

50.翻转对

题目链接:

题目描述:

题目示例:

题目解析:

解法(归并排序):

算法思路:

算法总结及流程解析:

结束语


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

题目链接:

315. 计算右侧小于当前元素的个数 - 力扣(LeetCode)

题目描述:

题目示例:

解法(归并排序):

算法思路:

      这一道题的解法与 求数组中的逆序对 的解法是类似的,但是这一道题要求的不是求总的个数,而是要返回一个数组,记录每一个元素的右边有多少个元素比自己小。

      但是在我们归并排序的过程中,元素的下标是会跟着变化的,因此我们需要一个辅助数组,来将数组元素和对应的下标绑定在一起归并,也就是再归并元素的时候,顺势将下标也转移到对应的位置上。

      由于我们要快速统计出某一个元素后面有多少个比它小的,因此我们可以利用求逆序对的第二种方法。

C++算法代码:

class Solution { public: vector<int> counts; vector<int> index; //记录nums中当前元素的原始下标 vector<int> tmp; vector<int> tmpi; //临时记录合并后对应元素位置变化下标随之变化的数组(保证元素和原始下标始终绑定) vector<int> countSmaller(vector<int>& nums) { counts.resize(nums.size()); index.resize(nums.size()); tmp.resize(nums.size()); tmpi.resize(nums.size()); //初始化index,使得nums每个元素下标和index一一对应 for(int i = 0; i <nums.size(); i++) { index[i] = i; } mergesort(nums, 0, nums.size() - 1); return counts; } void mergesort(vector<int>& nums, int left, int right) { if(left == right) { return; } int mid = (right - left) / 2 + left; mergesort(nums, left, mid); mergesort(nums, mid + 1, right); int cur1 = left, cur2 = mid + 1, i = 0; while(cur1 <= mid && cur2 <= right) { if(nums[cur1] > nums[cur2]) { counts[index[cur1]] += right - cur2 + 1; //重点 //因为index[cur1]始终是cur1当前元素的原始下标,所以不管当前元素位置怎么变化 //counts[index[cur1]]的位置都不会变 tmpi[i] = index[cur1]; tmp[i++] = nums[cur1++]; } else { tmpi[i] = index[cur2]; tmp[i++] = nums[cur2++]; } } while(cur1 <= mid) { tmpi[i] = index[cur1]; tmp[i++] = nums[cur1++]; } while(cur2 <= right) { tmpi[i] = index[cur2]; tmp[i++] = nums[cur2++]; } for(int j = left; j <= right; j++) { nums[j] = tmp[j - left]; index[j] = tmpi[j - left]; } } };

算法总结及流程解析:

50.翻转对

题目链接:

493. 翻转对 - 力扣(LeetCode)

题目描述:

题目示例:

题目解析:

      翻转对和逆序对的定义大同小异,逆序对是前面的数要大于后面的数。而翻转对是前面的一个数要大于后面某个数的两倍。因此,我们依旧可以用归并排序的思想来解决这个问题。

解法(归并排序):

算法思路:

      大思路与求逆序对的思路一样,就是利用归并排序的思想,将求整个数组的翻转对的数量,转换成三部分:左半区间翻转对的数量,右半区间翻转对的数量,一左一右选择时翻转对的数量。重点就是在合并区间过程中,如何计算出翻转对的数量。

      与上个问题不同的是,上一道题我们可以一边合并一遍计算,但是这道题要求的是左边元素大于右边元素的两倍,如果我们直接合并的话,是无法快速计算出翻转对的数量的。

      因此我们需要在归并排序之前完成翻转对的统计

class Solution { public: vector<int> tmp; int count = 0; int reversePairs(vector<int>& nums) { tmp.resize(nums.size()); mergesort(nums, 0, nums.size() - 1); return count; } void mergesort(vector<int>& nums, int left, int right) { if(left >= right) { return; } int mid = (right - left) / 2 + left; mergesort(nums, left, mid); mergesort(nums, mid + 1, right); //这里需要注意:当我们左右区间排完序后,按照之前逆序对类似题目 //我们是求值和合并数组同时进行的 //因为左边大于右边正好就可以求值顺带可以进行合并操作 //但是这里求助的条件是左边需要大于右边的两倍 //也就是说如果左边大于右边我们不一定能够求值,但是必须要进行合并,就会出现问题 //所以如果不能同时进行操作我们就将求值和合并分开操作:先进行求值再进行合并数组 int cur1 = left, cur2 = mid + 1; while(cur1 <= mid && cur2 <= right)//降序操作 { //当左边大于右边的两边才会进行求值 if(nums[cur1] > (long long)2 * nums[cur2]) { count += right - cur2 + 1; cur1++; } else { cur2++; } }//当出了循环说明要么cur1>mid要么cur2>right,不管哪种情况此时翻转对是求完了 //无需像合并数组那样处理剩余部分 cur1 = left; cur2 = mid + 1; int i = 0; while(cur1 <= mid && cur2 <= right) { if(nums[cur1] > nums[cur2]) { tmp[i++] = nums[cur1++]; } else { tmp[i++] = nums[cur2++]; } } while(cur1 <= mid) { tmp[i++] = nums[cur1++]; } while(cur2 <= right) { tmp[i++] = nums[cur2++]; } // while(cur1 <= mid && cur2 <= right)//升序操作同样如此 // { // 当左边大于右边的两边才会进行求值 // if(nums[cur1] > (long long)2 * nums[cur2]) // { // count += mid - cur1 + 1; // cur2++; // } // else // { // cur1++; // } // } // cur1 = left; // cur2 = mid + 1; // int i = 0; // while(cur1 <= mid && cur2 <= right) // { // if(nums[cur1] > nums[cur2]) // { // tmp[i++] = nums[cur2++]; // } // else // { // tmp[i++] = nums[cur1++]; // } // } // while(cur1 <= mid) // { // tmp[i++] = nums[cur1++]; // } // while(cur2 <= right) // { // tmp[i++] = nums[cur2++]; // } for(int i = left; i <= right; i++) { nums[i] = tmp[i - left]; } } };

算法总结及流程解析:

结束语

      到此,49.计算右侧小于当前元素的个数,50.翻转对 这两道算法题就讲解完了。49题通过维护原始下标数组,在归并过程中统计右侧较小元素数量;50题则需先统计满足条件的翻转对数量,再进行归并排序。希望大家能有所收获!

Read more

从安装到代码提交:Git 远程协作中 90% 的问题都能在这里找到答案

从安装到代码提交:Git 远程协作中 90% 的问题都能在这里找到答案

工欲善其事,必先利其器。 目录 * 安装 Git 的步骤: * 本地Git与远程仓库连接及操作全指南 * 一、本地仓库初始化与远程仓库连接 * 1. 初始化本地Git仓库 * 2. 关联远程仓库 * 1. 查看当前分支状态 * 2. 新建本地分支 * 方法1:基于当前分支创建新分支 * 方法2:创建并直接切换到新分支(推荐) * 方法3:基于远程分支创建本地分支 * 3. 切换到已有的本地分支 * 二、分支管理与远程分支同步 * 1. 查看远程分支 * 2. 拉取远程分支到本地 * 三、代码提交与推送到远程仓库 * 1. 常规提交流程 * 2. 简化推送命令 * 四、远程仓库信息查看与更新 * 1. 查看远程仓库详细信息 * 2. 同步远程仓库最新数据 * 五、常见问题解决与优化配置 * 1. 网络与连接问题修复 * 2. 推送大文件或提升传输稳定性

By Ne0inhk
2025电赛E题开源:二维云台激光打靶系统全解析(基于STM32F407+K230)

2025电赛E题开源:二维云台激光打靶系统全解析(基于STM32F407+K230)

2025电赛E题:二维云台激光打靶系统全解析——基于STM32F407的视觉伺服控制 本文详细介绍2025年全国大学生电子设计竞赛E题《二维云台激光打靶系统》的完整实现方案。项目基于STM32F407微控制器,结合视觉追踪、PID控制、步进电机驱动等技术,实现高精度的激光自动瞄准与发射功能。 🎯 项目背景与意义 在自动化控制领域,视觉伺服系统是实现高精度定位与追踪的关键技术。本次分享的项目,源自 2025 年全国大学生电子设计竞赛的赛题,题目要求设计一套二维云台系统,需具备自动识别目标、控制激光精准命中的功能。 该项目历经多重挑战,最终斩获了广东省赛区的省一等奖。由于我在此次比赛中主要负责二维云台激光打靶系统的设计,因此仅针对 25 年电赛 e 题的瞄准模块部分进行解说,自动循迹小车的内容会略过。 这个项目的成功落地,既为电子设计竞赛提供了一套完整的参考方案,也为嵌入式视觉伺服系统的教学与研究提供了宝贵的实践案例。 📊 系统总体设计 系统架构图 二维云台激光打靶系统 ├── 感知层(视觉模块) │ ├── 摄像头采集 │ └── 目标坐标提取 ├── 控制层(主控板

By Ne0inhk
OpenAI 开源模型 gpt-oss 本地部署详细教程

OpenAI 开源模型 gpt-oss 本地部署详细教程

OpenAI 最近发布了其首个开源的开放权重模型gpt-oss,这在AI圈引起了巨大的轰动。对于广大开发者和AI爱好者来说,这意味着我们终于可以在自己的机器上,完全本地化地运行和探索这款强大的模型了。 本教程将一步一步指导你如何在Windows和Linux系统上,借助极其便捷的本地大模型运行框架Ollama,轻松部署和使用 gpt-oss 模型。 一、准备工作:系统配置与性能预期 在开始之前,了解运行环境非常重要。本次部署将在我的个人电脑上进行,下面是推荐配置: * CPU: 现代多核 CPU,如 Intel Core i7 或 AMD Ryzen 7 系列 * 内存 (RAM): 32 GB 或更多 * 显卡 (GPU): 强烈推荐 NVIDIA GeForce RTX 4090 (24 GB 显存)。这是确保大型模型流畅运行与高效微调的理想选择。 * 操作系统: Linux 或 Windows

By Ne0inhk

OpenClaw相关的开源AI项目汇总大全:本文涵盖近期所有OpenClaw相关的GitHub高星star热门项目

OpenClaw相关的开源AI项目汇总大全:本文涵盖近期所有OpenClaw相关的GitHub高星star热门项目 💡 导读 GitHub上这些OpenClaw开源项目,Star数为什么能破千?我们扒了13个宝藏仓库后发现… 有人用OpenClaw给钉钉搭了智能助手,有人在飞书里养了个AI女友Clawra,还有人把记忆层memU玩成了第二大脑——而这些全部免费开源! 2026年OpenClaw热度飙升,但官方文档晦涩、部署门槛高劝退无数人?别慌!本文汇总了OpenClawInstaller、OneClaw、Moltworker等13个硬核开源项目,覆盖:✅ 一键部署工具(零代码上手)✅ 钉钉/企微/飞书/微信全平台接入方案✅ 云端托管+本地Sandbox双模式✅ 记忆层memU、技能库Skills、甚至AI女友Clawra… 收藏这一篇,省掉你100个小时的踩坑时间! 文章目录 * OpenClaw相关的开源AI项目汇总大全:本文涵盖近期所有OpenClaw相关的GitHub高星star热门项目 * 💡 导读 * 一、OpenClawInstall

By Ne0inhk