【LeetCode热题100】分治-归并

embedded/2024/10/23 15:30:20/

这篇博客记录了分治-归并的几道题目,包括排序数组、逆序对、计算右侧小于当前元素的个数、翻转对这几道题目。

//归并排序
class Solution 
{//创建一个全局变量,这样可以提高效率vector<int> tmp;
public:void _sortArray(vector<int>& nums,int left,int right){if(left >= right) return;//1.选择中间点划分区间int mid = left + (right - left)/2;//[left,mid] [mid+1,right]//2.把左右区间排序_sortArray(nums,left,mid);_sortArray(nums,mid+1,right);//3.合并两个有序数组int p1 = left,p2 = mid+1,i=0;while(p1 <= mid && p2 <= right)tmp[i++] = nums[p1]<=nums[p2]?nums[p1++]:nums[p2++];//4.处理没有遍历的数组while(p1 <= mid) tmp[i++] = nums[p1++];while(p2 <= right) tmp[i++] = nums[p2++];//5.还原for(int i = left ; i <= right ; i++){nums[i] = tmp[i-left];}}vector<int> sortArray(vector<int>& nums) {tmp.resize(nums.size());_sortArray(nums,0,nums.size()-1);return nums;}};

题目分析:我们可以归并排序,归并排序的思想就是先找一个中间值,然后把其左边区间也归并排序,然后其右边区间也归并排序,然后再把两个排序好的左右两个有序数组合并,合并两个有序数组的思路是双指针,分别指向左右区间的起始,另创建一个空数组,比较这两个指针指向的元素大小,小的放进这个空数组,直到遍历完。

所以,归并排序类似二叉树的后序遍历,而快速排序类似二叉树的前序遍历

class Solution {int v[50001];
public:int MergeSort(vector<int>& nums,int left,int right){if(left >= right) return 0;//1.找中间点,将数组分成两部分//int mid = left+(right-left)/2;int mid = (left + right) >> 1;//[left,mid] [mid+1,right] 升序int ret = 0;//2.左边的个数+排序 右边的个数+排序ret += MergeSort(nums,left,mid);ret += MergeSort(nums,mid+1,right);int cur1 = left,cur2 = mid+1,i=0;//3.一左一右的个数while(cur1 <= mid && cur2 <= right){if(nums[cur1] > nums[cur2]) {   ret += mid - cur1 + 1;v[i++] = nums[cur2++];}else{v[i++] = nums[cur1++];}}// while(cur1 <= mid && cur2 <= right) v[i++] = nums[cur1] < nums[cur2] ? nums[cur1] : nums[cur2];while(cur1 <= mid) v[i++] = nums[cur1++];while(cur2 <= right) v[i++] = nums[cur2++];for(int i = left ; i <= right ; i++){nums[i] = v[i-left];}return ret;}int reversePairs(vector<int>& record) {return MergeSort(record,0,record.size()-1);}
};

题目分析:我们可以使用归并排序解决这道题,将数组分为两部分,左半部分->排序->右半部分->排序->一左一右,其中我们在一左一右中找逆序对时,只需要固定右半部分一个值,然后去左半部分找有多少大于这个值的元素,这种方法要求归并排序是升序

也可以固定左半部分一个值,然后去右半部分找有多少小于这个值的元素,这种方法要求归并排序是降序

假设是升序,在将数组分成一左一右后,[left,mid][mid+1,right],cur1和cur2分别遍历这两部分,nums[cur1]和nums[cur2]的大小关系有两种情况,

1)nums[cur1] <= nums[cur2],cur1++

2)nums[cur1] > nums[cur2],ret += mid - cur1+1,cur2++

class Solution {vector<int> ret;vector<int> nums_tmp;int index[500010];int index_tmp[500010];public:void MergeSort(vector<int>& nums,int left,int right){if(left >= right) return;int mid = (left + right) >> 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]){ret[index[cur1]] += (right - cur2 + 1);index_tmp[i] = index[cur1];nums_tmp[i++] = nums[cur1++];}else{index_tmp[i] = index[cur2];nums_tmp[i++] = nums[cur2++];}}while(cur1 <= mid){index_tmp[i] = index[cur1];nums_tmp[i++] = nums[cur1++];}while(cur2 <= right){index_tmp[i] = index[cur2];nums_tmp[i++]= nums[cur2++];}for(int i = left; i <= right ; i++){nums[i] = nums_tmp[i-left];index[i] = index_tmp[i-left];}}vector<int> countSmaller(vector<int>& nums) {ret.resize(nums.size());nums_tmp.resize(nums.size());for(int i = 0; i < nums.size() ; i++){index[i]=i;}MergeSort(nums,0,nums.size()-1);return ret;}
};

题目分析:我们要找出之后有多少元素比我小,依照上题思路,需要选择降序,也是采用分支排序的方法,

为了找到对应的下标,刚开始就要创建一个数组index,里面是各个元素下表,在排序过程中,index也要跟着nums元素位置变化而变化。

class Solution {//vector<int> tmp;int tmp[50010];
public:int _reversePairs(vector<int>& nums,int left,int right){if(left >= right) return 0;int ret = 0;int mid = (left + right)>>1;ret += _reversePairs(nums,left,mid);ret += _reversePairs(nums,mid+1,right);int cur1 = left,cur2 = mid+1;//1.先找翻转对的数量while(cur1 <= mid && cur2 <= right){if(0.5*nums[cur1] > nums[cur2]){ret += (right - cur2 + 1);cur1++;}else{cur2++;}}//2.合并两个有序数组cur1 = left,cur2=mid+1;int 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(i = left; i <= right ; i++){nums[i] = tmp[i-left];}return ret;}int reversePairs(vector<int>& nums) {//tmp.resize(nums.size());return _reversePairs(nums,0,nums.size()-1);   }
};

题目分析:这道题我们依然用分治的思想。将一个数组分成两部分,先找左半部分的翻转对,再找右半部分的翻转对,最后再找一左一右的翻转对。

仍然有两个策略

1)计算当前元素后面,有多少元素的两倍比我少,要求数组降序。

if(nums[cur1] > 2*nums[cur2]) ret += right-cur2+1

2)计算当前元素之前,有多少元素的一半比我大,要求数组升序。

if(nums[cur1] > 2*nums[cur2]) ret += mid-left+1


http://www.ppmy.cn/embedded/129848.html

相关文章

Maven--简略

简介 Apache旗下的一款开源项目&#xff0c;用来进行项目构建&#xff0c;帮助开发者管理项目中的jar及jar包之间的依赖&#xff0c;还拥有项目编译、测试、打包的功能。 管理方式 统一建立一个jar仓库&#xff0c;把jar上传至统一的仓库&#xff0c;使用时&#xff0c;配置…

系统性能优化——绑核

简要 绑核正如其名&#xff0c;将线程/进程绑定在一个或多个CPU核心。该技术可以使进程或线程在特定的处理器上运行&#xff0c;而不会被操作系统调度到其他处理器上。这里有两层含义。 如果线程被绑定在指定核心上&#xff0c;则只会在该核心上运行&#xff0c;即使其他核心…

ReactNative项目构建目录找不到问题解决

要检查你的 Expo 项目中 TypeScript 的配置&#xff0c;你需要查看 tsconfig.json 文件。这个文件位于项目的根目录&#xff0c;并且包含了 TypeScript 编译器的所有配置选项。以下是一些基本步骤来检查和理解你的 tsconfig.json 文件&#xff1a; 定位 tsconfig.json 文件&…

基于STM32设计的智能婴儿床(华为云IOT)(244)

文章目录 一、前言1.1 项目介绍【1】开发背景【2】项目实现的功能【3】项目硬件模块组成【4】ESP8266工作模式配置1.2 设计思路【1】整体设计思路【2】整体构架【3】上位机开发思路1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献【4】摘要1.4 开发工具的选择【1…

HarmonyOS的DevEcoStudio安装以及初步认识

目录 1.DevEco下载 2.DevEco安装 3. 未开启Hyper-V 1--开启Hyper-v流程 4.编译错误 5.目录结构 1&#xff09;AppScope 2&#xff09;entry: 3&#xff09;build 4&#xff09;entry->src 5&#xff09;entry->src->main->etc 6&#xff09;entry->src->main…

C++字符串函数(详细解析) √

1、查找find:返回第一次出现ab的"位置"&#xff0c;没有则返回乱码 (1)格式&#xff1a;str.find("查找的内容"&#xff0c;从下标2开始往后查找包括下标2) str.find("ab",2); (2)格式&#xff1a;str.find("查找的内容"…

多仓多门店库存管理与系统设计

库存是供应链之魂。 在新零售模式下,仓库和门店遍布全国甚至全球,如果库存管理不到位,就没法给企业赋能,无法给客户带来极致购物体验。 商品的库存数是整个供应链业务的核心,是业务能顺利流转的基础,如何才能在系统设计上保证库存数据的实时性和准确性? 我们需要设计…

数据分箱:决策树得到特征的分箱区间后后怎么映射到原数据中?

以下是将bins_intervals的值映射回原数据的示例代码&#xff1a; import pandas as pd import numpy as np# 假设原数据 data pd.DataFrame({feature_to_bin: [10, 20, 30, 40, 50, 60, 70, 80, 90] })# 假设决策树得到的分箱区间 bins_intervals [(0, 30), (30, 60), (60, …