【优选算法】D&C-Mergesort-Harmonies:分治-归并的算法之谐

【优选算法】D&C-Mergesort-Harmonies:分治-归并的算法之谐

文章目录

本篇是优选算法之分治-归并,简单来说就是一个不断分组排序再合并的过程

1.概念解析

🚩什么是分治-归并?

分治归并(基于分治思想的归并排序)是分治算法(Divide and Conquer)在排序问题中的经典应用,核心是通过 “拆分 - 排序 - 合并” 三步,将无序数组转化为有序数组,本质是 “化繁为简、再合简为繁” 的解题思路

2.排序数组

✏️题目描述:

在这里插入图片描述

✏️示例:

在这里插入图片描述
传送门:排序数组

题解:

在这里插入图片描述

本质上分治归并就是一个后序遍历,而快排就是一个前序遍历,不断向下细分数组,然后从下往上把左右两分支的数组排序并合并,以此向上循环往复

💻细节问题:

  • int mid = left + ((right - left) >> 1) 相当于 int mid = left + ((right - left) / 2),二进制的算法效率更高,且该计算中间值的方法能避免整数溢出
  • 最后一步合并数组,nums[left + j] = tmp[j] 而不是 nums[j] = tmp[j],是因为 left 不一定是 0,即不一定是对原来的整个数组进行排序,可能只对数组一部分进行排序
  • 数组排序并不影响逆序对的计算,因为是左右两部分比较,内部已经在递归过程中计算过了

💻代码实现:

#include<iostream>#include<vector>usingnamespace std;classSolution{ vector<int> tmp;public: vector<int>sortArray(vector<int>& nums){ tmp.resize(nums.size());mergeSort(nums,0, nums.size()-1);return nums;}voidmergeSort(vector<int>& nums,int left,int right){if(left >= right){return;}int mid = left +((right - left)>>1);mergeSort(nums, left, mid);mergeSort(nums, mid +1, right);int cur1 = left, cur2 = mid +1, i =0;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 =0; j <= right - left;++j){ nums[left + j]= tmp[j];}}};

3.交易逆序对的总数

✏️题目描述:

在这里插入图片描述

✏️示例:

在这里插入图片描述
传送门:交易逆序对的总数

题解:

在这里插入图片描述

因为归并排序的 “分治 + 有序合并” 特性,完美匹配逆序对统计的核心需求 —— 高效拆分问题、批量计算逆序对,这是暴力枚举做不到的,当 [left,mid][mid+1,right] 进行互相比较时,如果是升序,获取到 record[cur1] >= record[cur2] 时,由于是有序,所以 cur2 往后都是小于 cur1 对应的数的,所以能直接得到很多对逆序数。用降序也是同理

💻代码实现:

classSolution{ vector<int> tmp;public:intreversePairs(vector<int>& record){ tmp.resize(50010);returnmergeSort(record,0, record.size()-1);}intmergeSort(vector<int>&record,int left,int right){if(left >= right){return0;}int ret =0;int mid = left +((right - left)>>1); ret +=mergeSort(record, left, mid); ret +=mergeSort(record, mid +1, right);int cur1 = left, cur2 = mid +1, i =0;while(cur1 <= mid && cur2 <= right){if(record[cur1]<= record[cur2]){ tmp[i++]= record[cur1++];}else{ ret += mid - cur1 +1; tmp[i++]= record[cur2++];}}while(cur1 <= mid){ tmp[i++]= record[cur1++];}while(cur2 <= right){ tmp[i++]= record[cur2++];}for(int j =0; j < right - left +1;++j){ record[j + left]= tmp[j];}return ret;}};

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

✏️题目描述:

在这里插入图片描述

✏️示例:

在这里插入图片描述
传送门:计算右侧小于当前元素的个数

题解:

在这里插入图片描述


这题和上一题思路基本一致,唯一的难点就是要额外创建一个数组进行值和下表的绑定,因为题目要求的是返回每个 index 对应的值,有人就问了为什么不能用哈希表,可以是可以但是有重复值的话会很麻烦,因此额外创建一个数组进行 index 和值的绑定更方便,index 数组跟着 nums 数组移动就行

💻代码实现:

classSolution{ vector<int> ret; vector<int> index;int tmpNums[500010];int tmpindex[500010];public: vector<int>countSmaller(vector<int>& nums){int n = nums.size(); ret.resize(n,0); index.resize(n);for(int i =0; i < n;++i){ index[i]= i;}mergeSort(nums,0, n -1);return ret;}voidmergeSort(vector<int>& nums,int left,int right){if(left >= right){return;}int mid = left +((right - left)>>1);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]){ tmpNums[i]= nums[cur2]; tmpindex[i++]= index[cur2++];}else{ ret[index[cur1]]+= right - cur2 +1; tmpNums[i]= nums[cur1]; tmpindex[i++]= index[cur1++];}}while(cur1 <= mid){ tmpNums[i]= nums[cur1]; tmpindex[i++]= index[cur1++];}while(cur2 <= right){ tmpNums[i]= nums[cur2]; tmpindex[i++]= index[cur2++];}for(int j =0; j < right - left +1;++j){ nums[j + left]= tmpNums[j]; index[j + left]= tmpindex[j];}}};

5.翻转对

✏️题目描述:

在这里插入图片描述

✏️示例:

在这里插入图片描述
传送门:翻转对

题解:

在这里插入图片描述

思路还是利用归并解决,但是要提前计算符合题目要求的翻转对,如果在排序过程中进行计算,会漏掉部分翻转对

💻细节问题:

(long long)nums[cur1] <= 2 * (long long)nums[cur2] 防止溢出

💻代码实现:

classSolution{ vector<int> tmp;int ret =0;public:intreversePairs(vector<int>& nums){ tmp.resize(nums.size());mergeSort(nums,0, nums.size()-1);return ret;}voidmergeSort(vector<int>& nums,int left,int right){if(left >= right){return;}int mid = left +((right - left)>>1);mergeSort(nums, left, mid);zq mergeSort(nums, mid +1, right);int cur1 = left, cur2 = mid +1, i =0;while(cur2 <= right){while(cur1 <= mid &&(longlong)nums[cur1]<=2*(longlong)nums[cur2]){ cur1++;}if(cur1 > mid){break;} ret += mid - cur1 +1; cur2++;} cur1 = left, cur2 = mid +1;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++];}for(int j =0; j < right - left +1;++j){ nums[j + left]= tmp[j];}}};

希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

请添加图片描述

Read more

基于腾讯云HAI + DeepSeek快速设计自己的个人网页

基于腾讯云HAI + DeepSeek快速设计自己的个人网页

前言:通过结合腾讯云HAI 强大的云端运算能力与DeepSeek先进的 AI技术,本文介绍高效、便捷且低成本的设计一个自己的个人网页。你将了解到如何轻松绕过常见的技术阻碍,在腾讯云HAI平台上快速部署DeepSeek模型,仅需简单几步,就能获取一个包含个人简介、技能特长、项目经历及联系方式等核心板块的响应式网页。 目录 一、DeepSeek模型部署在腾讯云HAI 二、设计个人网页 一、DeepSeek模型部署在腾讯云HAI 把 DeepSeek 模型部署于腾讯云 HAI,用户便能避开官网访问限制,直接依托腾讯云 HAI 的超强算力运行 DeepSeek-R1 等模型。这一举措不仅降低了技术门槛,还缩短了部署时间,削减了成本。尤为关键的是,凭借 HAI 平台灵活且可扩展的特性,用户能够依据自身特定需求定制专属解决方案,进而更出色地适配特定业务场景,满足各类技术要求 。 点击访问腾讯云HAI控制台地址: 算力管理 - 高性能应用服务 - 控制台 腾讯云高性能应用服务HAI已支持DeepSeek-R1模型预装环境和CPU算力,只需简单的几步就能调用DeepSeek - R1

By Ne0inhk
AI革命先锋:DeepSeek与蓝耘通义万相2.1的无缝融合引领行业智能化变革

AI革命先锋:DeepSeek与蓝耘通义万相2.1的无缝融合引领行业智能化变革

云边有个稻草人-ZEEKLOG博客 目录 引言 一、什么是DeepSeek? 1.1 DeepSeek平台概述 1.2 DeepSeek的核心功能与技术 二、蓝耘通义万相2.1概述 2.1 蓝耘科技简介 2.2 蓝耘通义万相2.1的功能与优势 1. 全链条智能化解决方案 2. 强大的数据处理能力 3. 高效的模型训练与优化 4. 自动化推理与部署 5. 行业专用解决方案 三、蓝耘通义万相2.1与DeepSeek的对比分析 3.1 核心区别 3.2 结合使用的优势 四、蓝耘注册流程 五、DeepSeek与蓝耘通义万相2.1的集成应用 5.1 集成应用场景 1. 智能医疗诊断

By Ne0inhk
如何通过 3 个简单步骤在 Windows 上本地运行 DeepSeek

如何通过 3 个简单步骤在 Windows 上本地运行 DeepSeek

它是免费的——社区驱动的人工智能💪。         当 OpenAI 第一次推出定制 GPT 时,我就明白会有越来越多的人为人工智能做出贡献,并且迟早它会完全由社区驱动。         但从来没有想过它会如此接近😂让我们看看如何在 Windows 机器上完全免费使用第一个开源推理模型!  步骤 0:安装 Docker 桌面         我确信很多人已经安装了它,所以可以跳过,但如果没有 — — 这很简单,只需访问Docker 的官方网站,下载并运行安装 👍         如果您需要一些特定的设置,例如使用 WSL,那么有很多指导视频,请查看!我将继续下一步。 步骤 1:安装 CUDA 以获得 GPU 支持         如果您想使用 Nvidia 显卡运行 LLM,则必须安装 CUDA 驱动程序。(嗯……是的,它们需要大量的计算能力)         打开CUDA 下载页面,

By Ne0inhk
在 VSCode 中本地运行 DeepSeek,打造强大的私人 AI

在 VSCode 中本地运行 DeepSeek,打造强大的私人 AI

本文将分步向您展示如何在本地安装和运行 DeepSeek、使用 CodeGPT 对其进行配置以及开始利用 AI 来增强您的软件开发工作流程,所有这些都无需依赖基于云的服务。  步骤 1:在 VSCode 中安装 Ollama 和 CodeGPT         要在本地运行 DeepSeek,我们首先需要安装Ollama,它允许我们在我们的机器上运行 LLM,以及CodeGPT,它是集成这些模型以提供编码辅助的 VSCode 扩展。 安装 Ollama Ollama 是一个轻量级平台,可以轻松运行本地 LLM。 下载Ollama 访问官方网站:https://ollama.com * 下载适合您的操作系统(Windows、macOS 或 Linux)的安装程序。 * 验证安装 安装后,打开终端并运行: ollama --version  如果 Ollama 安装正确,

By Ne0inhk