力扣--分治(快速排序)算法题II:数组中的第K个最大元素(Top K问题),LCR159.库存管理III

上篇文章:力扣--分治(快速排序)算法题I:颜色分类,排序数组

目录

1.数组中的第K个最大元素

理解题意

算法原理

2.库存管理III

理解题意

算法原理


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 的元素个数)

  1. 当 a > cnt 时: 最小的 cnt 个元素全部都在 < key 的区间内。递归在 [l, left] 中找最小的 cnt 个元素。

  2. 当 a + b >= cnt 时: < key 和 == key 的元素总数已经达到或超过了 cnt。因为题目不要求输出顺序,此时数组左端的 cnt 个元素已经是最小的了,直接 return 结束划分。

  3. 前两种都不满足时: 左边和中间的元素全拿走也不够 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];
    }
};

本章完。

相关推荐
专注仿真3 小时前
知识问答模型用到的算法集详解及代码实例
python·算法·代码·大模型训练·控制算法
罗西的思考4 小时前
【轻量化复刻大模型 / KIMI K3】AttnRes 模块交互式演示
人工智能·算法·机器学习
小七在进步4 小时前
string的使用(1)
c++·visual studio
白杨尚青5 小时前
C++进阶篇(六):map 和 set 的模拟实现——用红黑树封装 mymap/myset(迭代器 + operator[])
开发语言·c++·迭代器·stl·set·map·红黑树
好悬给我拽开线8 小时前
ZILOT 论文解析
算法
kloc8 小时前
聊天室项目入口网关子服务的实现
linux·c++
饮水桶_T9 小时前
JAVA IO流笔记
开发语言·数据结构·算法
星夜离尘5610 小时前
MATLAB 离散数据分箱:半开区间、末端点与计数、加权和、平均
算法·matlab
Pniubi10 小时前
力扣76.最小覆盖子串
算法·leetcode·职场和发展
地平线开发者10 小时前
征程6|用 hrt\_model\_exec 看清 YOLOv5x 的输入、原始输出和后处理
人工智能·算法