【LeetCode热题100】分治-快排

devtools/2024/10/18 12:20:42/

本篇博客记录分治快排的4道题目:颜色分类、排序数组、数组中的第K个最大元素、数组中最小的N个元素(库存管理)。

class Solution {
public:void sortColors(vector<int>& nums) {int n = nums.size();int left = -1,right = n;for(int i = 0 ; i < right ; ){if(nums[i] == 0) swap(nums[++left],nums[i++]);else if(nums[i] == 1) i++;else swap(nums[--right],nums[i]);}}
};

题目分析:本题的目的旨在将nums的元素0、1、2分成三块,打算采取三指针的方法。使用left、right、i三个变量,其中,left指向全0区间的最右侧,right指向全2区间的最左侧,i指向待扫描的下一个元素,这样就把整个区间划分为4块,包括:

[0,left]:全0区域

[left+1,i-1]:全1区域

[i,right-1]:待扫描的区域

[right,n-1]:全2区域

划分好区域后,刚开始让left指向nums的左侧,即left=-1,right指向nums的右侧,即right=n,i指向nums中的第一个元素,nums[i]就会有三种情况:0、1、2。对于这三种情况,处理的动作如下图:

class Solution {
public:int GetRef(vector<int>& nums , int left , int right){return nums[rand()%(right - left + 1) + left];}void _sortArray(vector<int>& nums, int left, int right){if(left >= right) return;int ref = GetRef(nums, left, right);int l = left - 1, r = right + 1, i = left;while(i < r){if(nums[i] < ref) swap(nums[++l],nums[i++]);else if(nums[i] == ref) i++;else swap(nums[--r],nums[i]);}//[left,l] [l+1,r-1] [r,right] _sortArray(nums,left,l);_sortArray(nums,r,right);}vector<int> sortArray(vector<int>& nums) {srand(time(NULL));_sortArray(nums, 0 , nums.size() - 1);return nums;}
};

题目分析:我们实现快排要用到“颜色分类”这道题的思想,向数组划分为三块,

这样迭代一次之后,[left+1,right-1]之间的元素已经排好,继续递归[0,left]和[right,n-1]即可。

在选择基准元素key时,我们可以使用随机的方式选取,ref = nums[rand()%(right-left+1)+left]。

class Solution {
public:int GetRef(vector<int>& nums,int left, int right){return nums[rand()%(right-left+1)+left];}int sort(vector<int>& nums,int left, int right, int k){if(left == right) return nums[left];//1.随机选择基准元素int ref = GetRef(nums, left, right);//2.根据基准元素将数组分三块int l = left-1,r = right+1;for(int i = left ; i < r ; ){if(nums[i] < ref) swap(nums[i++],nums[++l]);else if(nums[i] > ref) swap(nums[i],nums[--r]);else i++;}//3.分情况讨论//[left,l][l+1,r-1][r,right]int c = right - r + 1, b = r - l -1;if(c >= k) return sort(nums,r,right,k);else if(b+c >= k) return ref;else return sort(nums,left,l,k-b-c);}int findKthLargest(vector<int>& nums, int k) {srand(time(NULL));return sort(nums,0,nums.size()-1,k);}
};

题目分析:这道题的基础依然是上面数组分三块+随机选择基准元素的思想,我们第一次将数组分成三块,[left,l][l+1,r-1][r,right],假设这三个区间的长度分别是a、b、c,然后分情况讨论:

1)c>=k,去[r,right],找第k大

2)b+c>=k,返回ref

3)如果1)和2)不成立,去[l,left],找第k-b-c大        

class Solution {
public:vector<int> inventoryManagement(vector<int>& nums, int cnt) {srand(time(nullptr));qsort(nums,0,nums.size()-1,cnt);return {nums.begin(),nums.begin()+cnt};}int GetRef(vector<int>& nums,int left,int right){return nums[rand()%(right-left+1)+left];}void qsort(vector<int>& nums,int left,int right,int cnt){if(left == right) return;int ref = GetRef(nums,left,right);int l = left - 1,r = right + 1,i = left;while(i < r){if(nums[i] < ref) swap(nums[++l],nums[i++]);else if(nums[i] > ref) swap(nums[--r],nums[i]);else i++;}//[left,l][l+1,r-1][r,right]int a = l - left + 1,b = r - 1 - (l + 1) + 1,c = right -r + 1;if(a > cnt) qsort(nums,left,l,cnt);else if(a + b >= cnt) return;else qsort(nums,r,right,cnt - a - b);}
};

题目分析:这道题我们有多种解法,解法1是把这些数放到一个容器中,然后进行排序,时间复杂度是OlogN。解法2是把这些数放到一个大堆里,取堆顶元素,时间复杂度是OlogK。我们这里用第三种解法,快速排序,也是利用数组分三块+随机选择基准元素的思想,在使用这个排序完一遍后,数组被分成了三块,[left,l][l+1,r-1][r,right],假设这几块的区间长度分别为a、b、c:

① a>k,继续在[left,l]中找出最小的元素。

② a+b>=k,直接返回

③ ①和②都不成立,找[right,r]中最小的k-a-b个元素,在加上[left,l]和[l+1,r-1]之间的元素。


http://www.ppmy.cn/devtools/125390.html

相关文章

Android中的Activity(案例+代码+效果图)

目录 1.Activity的生命周期 核心生命周期回调 1&#xff09;onCreate() 2&#xff09;onStart() 3&#xff09;onResume() 4&#xff09;onPause() 5&#xff09;onStop() 6&#xff09;onRestart() 7&#xff09;onDestroy() 8&#xff09;生命周期图示 10&#xff09;注意事项…

PyCharm打开及配置现有工程(详细图解)

本文详细介绍了如何利用Pycharm打开一个现有的工程&#xff0c;其中包括编译器的配置。 PyCharm打开及配置现有工程 1、打开工程2、配置编译器 1、打开工程 双击PyCharm软件&#xff0c;点击左上角 文件 >> 打开(O)… 选中想要打开的项目之后点击“确定” 2、配置编译器…

【进阶OpenCV】 (12)--人脸检测识别

文章目录 人脸识别一、获取分类器二、代码实现1. 图片预处理2. 加载人脸检测分类器3. 检测人脸4. 标注人脸 总结 人脸识别 要实现人脸识别首先要判断当前图像中是否出现了人脸&#xff0c;这就是人脸检测。只有检测到图像中出现了人脸&#xff0c;才能据此判断这个人到底是谁。…

实时语音转文字(基于NAudio+Whisper+VOSP+Websocket)

今天花了大半天时间研究一个实时语音转文字的程序&#xff0c;目的还包括能够唤醒服务&#xff0c;并把命令提供给第三方。 由于这方面的材料已经很多&#xff0c;我就只把过程中遇到的和解决方案简单说下。源代码开源在AudioWhisper: 实时语音转文字(基于NAudioWhisperVOSPWe…

解决新版Android studio不能连接手机的问题

我要说的是一个特例&#xff0c;装了22年的版本AS可以正常连接手机&#xff0c;装了23年以后新版本&#xff0c;AS不能正常连接手机了&#xff0c;但是在CMD控制台可以正常的执行adb命令&#xff0c;并且CMD和AS都是指向D:\android_sdk\platform-tools\adb.exe 一、 为什么会出…

应对网站IP劫持的有效策略与技术手段

摘要&#xff1a; IP劫持是一种常见的网络攻击方式&#xff0c;攻击者通过非法手段获取目标网站服务器的控制权&#xff0c;进而改变其网络流量的路由路径&#xff0c;导致用户访问错误的站点。本文将介绍如何识别IP劫持&#xff0c;并提供一系列预防和应对措施&#xff0c;以确…

基于Android11简单分析audio_policy_configuration.xml

开篇先贴上一个高通的例子&#xff0c;后续基于此文件做具体分析。 1 <?xml version"1.0" encoding"UTF-8" standalone"yes"?> 2 <!-- Copyright (c) 2016-2019, The Linux Foundation. All rights reserved 3 Not a Contribut…

C# 字符串(string)三个不同的处理方法:IsNullOrEmpty、IsInterned 、IsNullOrWhiteSpace

在C#中&#xff0c;string.IsNullOrEmpty、string.IsInterned 和 string.IsNullOrWhiteSpace 是三个不同的字符串处理方法&#xff0c;它们各自有不同的用途&#xff1a; 1.string.IsNullOrEmpty&#xff1a; 这个方法用来检查字符串是否为null或者空字符串&#xff08;"…