力扣--分治(快速排序)算法题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];
    }
};

本章完。

相关推荐
星夜离尘562 分钟前
MATLAB 工程实验:从相邻块均值手写重叠 Allan 偏差,数清有效项
算法·matlab·均值算法
careathers1 小时前
【数据结构】从堆到 PriorityQueue:手写一个优先级队列
数据结构
y1su2 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
residual_fan3 小时前
船用柴油机动态机动工况故障诊断:控制感知仿射网络(CAAN)的技术实现
人工智能·算法·数据挖掘·数据分析
syagain_zsx3 小时前
BRpc 二次封装:Channel 管理、服务管理与回调工厂
c++·学习·程序人生·rpc·谷歌
其实防守也摸鱼3 小时前
Cylab在线靶场——CTF中的通用技能
linux·数据库·学习·算法·靶场·ctf·学习网络安全
蓝悦无人机3 小时前
《Planning algorithms》读书笔记——第8章 反馈运动规划
算法·读书笔记·反馈运动规划
RaaS1004 小时前
Agent Skills 进了 Linux Foundation:2.8 亿次安装,但装 skill 还没有安全规范
人工智能·算法·架构
CV爱数码4 小时前
CT 重建从零开始(五):ASTRA Toolbox 上手——几何、投影器与算法
图像处理·算法·计算机视觉·ct
TunerT_TQ4 小时前
超立方体Ramsey(openai/math 家族171)H11攻坚日志|D60–D69:Star分组重数、二幂坐标群、奇偶入射语义与Site‑Level候选计数形式化闭环
算法