上篇文章:力扣--分治(快速排序)算法题I:颜色分类,排序数组
目录
1.数组中的第K个最大元素
https://leetcode.cn/problems/kth-largest-element-in-an-array/description/


理解题意
此题为Top K中找第K个最大元素的问题,并且对时间复杂度有要求。
算法原理
本题为满足时间复杂度,所以使用快速排序的方式。
最核心的思路依旧同上一篇文章相同:数组分为三块+随机选择基准元素

当c >= key时,在[right, r]中找第K大
当c + b >= key时,返回key
当前两个不成立时,去[l, left]找第k - b - c大。
class Solution
{
public:
int findKthLargest(vector<int>& nums, int k)
{
srand(time(NULL));
return qsort(nums, 0, nums.size() - 1, k);
}
int qsort(vector<int>& nums, int l, int r, int k)
{
if(l == r) return nums[l];
// 随机数
int key = getRandom(nums, l, r);
// 分三步
int i = l, left = l - 1, right = r + 1;
while(i < right)
{
if(nums[i] < key) swap(nums[++left], nums[i++]);
else if(nums[i] == key) i++;
else swap(nums[--right], nums[i]);
}
// 分情况
int c = r - right + 1, b = right - left - 1;
if(c >= k) return qsort(nums, right, r, k);
else if(b + c >= k) return key;
else return qsort(nums, l, left, k - b - c);
}
int getRandom(vector<int>& nums, int left, int right)
{
return nums[rand() % (right - left + 1) + left];
}
};
2.库存管理III
https://leetcode.cn/problems/zui-xiao-de-kge-shu-lcof/description/


理解题意
给定一个整数数组 stock 和一个整数 cnt(即 k),要求找出数组中 最小的 cnt 个元素。返回顺序不限。同样要求时间复杂度尽可能低。这道题是经典的求"前K小"元素合集。
算法原理
同样使用快速选择算法 + 三路划分。但因为这次是找 前 K 小 ,我们的关注点转移到了数组的左边区间(小于 key 的区间)。
三路划分区间分布: [l, left] (全部 < key) | [left+1, right-1] (全部 == key) | [right, r] (全部 > key)
设 a = left - l + 1 (小于 key 的元素个数) 设 b = right - left - 1 (等于 key 的元素个数)
-
当
a > cnt时: 最小的cnt个元素全部都在< key的区间内。递归在[l, left]中找最小的cnt个元素。 -
当
a + b >= cnt时:< key和== key的元素总数已经达到或超过了cnt。因为题目不要求输出顺序,此时数组左端的cnt个元素已经是最小的了,直接return结束划分。 -
前两种都不满足时: 左边和中间的元素全拿走也不够
cnt个。我们需要保留前a + b个元素,并去右边> key的区间里再挑出剩下的cnt - a - b个元素。递归去[right, r]中找最小的cnt - a - b个元素。

代码:
class Solution
{
public:
vector<int> inventoryManagement(vector<int>& stock, int cnt)
{
srand(time(NULL));
qsort(stock, 0, stock.size() - 1, cnt);
return {stock.begin(), stock.begin() + cnt};
}
void qsort(vector<int>& stock, int l, int r, int cnt)
{
if(l >= r) return;
int key = getRandom(stock, l, r);
int i = l, left = l - 1, right = r + 1;
while(i < right)
{
if(stock[i] < key) swap(stock[++left], stock[i++]);
else if(stock[i] == key) i++;
else swap(stock[--right], stock[i]);
}
int a = left - l + 1, b = right - left - 1;
if(a > cnt) qsort(stock, l, left, cnt);
else if(a + b >= cnt) return;
else qsort(stock, right, r, cnt - a - b);
}
int getRandom(vector<int>& stock, int left, int right)
{
return stock[rand() % (right - left + 1) + left];
}
};
本章完。