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

本章完。

相关推荐
ysa0510301 小时前
运用map优化多次查询【Kadomatsu 子序列】
数据结构·c++·笔记·算法
TTTrees2 小时前
C++学习笔记(31):智能指针(shared_ptr)
c++
_饭团2 小时前
C 语言内存函数全解析:从 memcpy 到 memcmp 的使用与模拟实现
c语言·开发语言·c++·学习·算法·面试·改行学it
24白菜头2 小时前
第十五届蓝桥杯C&C++大学B组
数据结构·c++·笔记·学习·算法·leetcode·蓝桥杯
学嵌入式的小杨同学2 小时前
STM32 进阶封神之路(二十二):DMA 实战全攻略 ——ADC 采集 + 串口收发 + 内存复制(库函数 + 代码落地)
c++·stm32·单片机·嵌入式硬件·mcu·硬件架构·pcb
2401_884563242 小时前
C++中的观察者模式实战
开发语言·c++·算法
凌波粒2 小时前
LeetCode--704.二分查找(数组)
算法·leetcode·职场和发展
xiaoye-duck2 小时前
《算法题讲解指南:动态规划算法--路径问题》--11.按摩师,12.打家劫舍II
c++·算法·动态规划
历程里程碑2 小时前
43. TCP -2实现英文查中文功能
java·linux·开发语言·c++·udp·c#·排序算法