分治算法---快排

一、快排的概念

分治算法--将问题进行分类

1、颜色划分

(1)题目
(2)解题思路

我们可以定义三个指针,一个指针指向0的最后一个位置,一个指针指向2的第一个位置,这样就把他分为了三块,最后一个指针负责遍历数组,如果遇到0就将他移到第一个指针的前面,如果遇到2就把他移到第二个指针的后面

(3)代码书写
cpp 复制代码
class Solution
{
public:
    void sortColors(vector<int>& nums)
    {
        int n = nums.size();
        int left = -1;
        int right = n ;
        int i  = 0;
        while(i<right)
        {
            if(nums[i] == 0)
            {
                swap(nums[++left],nums[i++]);
            }
            else if(nums[i] == 1)
            {
                i++;
            }
            else
            {
                swap(nums[--right],nums[i]);
            }
        }
    }
};

2、排序数组

(1)题目
(2) 解题思路

我们找一个key值,依照上题将数组划分为三个部分,大于key,等于key,小于key

key值如何寻找,使用一个随机数,然后将随机数%(right - left +1)+left (这样得到的随机数时间复杂度无限接近于nlogn)

(3)代码书写
cpp 复制代码
class Solution
{
public:
    vector<int> sortArray(vector<int>& nums) 
    {
        srand(time(NULL));
        qsort(nums,0,nums.size()-1);
        return nums;
    }
    void qsort(vector<int>& nums, int l, int r)
    {
        if(l>=r) return ;
        int i = l; 
        int key = getRandom(nums,l,r);
        int left = l-1;
        int 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]);
            }
        }
        qsort(nums,l,left);
        qsort(nums,right,r);
    }
    int getRandom(vector<int>& nums, int left, int right)
    {
        int r = rand();
        return nums[r%(right - left + 1)+left];
    }
};

3、数组中第K个大的数

(1)题目
(2)解题思路

我们可以依照上题将数组划分为三个部分(小于key ,等于key,大于key),我们设三个部分的个数分别为a , b , c,因为是第K个大的数如果当k<c的时候我们可以知道第K个大的数一定在第三部分,我们在将第三个部分进行划分,当k<c+b且k>c我们知道第K个大的数一定在第二部分,因为第二部分的值都是等于key的所以,第K个大的数就是K,如果不满足以上的两个情况那么第K个大的数一定在第一部分,我们在将第一部分进行划分.

(3)代码书写
cpp 复制代码
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;
        int left = l-1;
        int 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;
        int a = left;
        int 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];
    }
};

4、最小的k个数

1、题目
2、解题思路

同上道题一样,我们首先得到随机值key,将他们分为三部分,设三个部分的长度分为a,b,c. 因为要找前k个小的值,如果a>k,那么值一定在第一部分,我们在将第一部分的划分,如果不满足第一个条件,但是满足a+b>k,那么值一定包含在第一部分和第二部分中,直接返回前k个值(第而部分的 值一样),都不满足,那么值一定包含在第一部分,第二部分和第三部分,我们接着将第三部分的数据进行划分(找前k-a-b个)

3、代码实现
cpp 复制代码
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 k)
    {
        if(l>=r) return ;
        int key = getRand(stock,l,r);
        int left = l - 1;
        int right = r + 1;
        int i = l;
        while(i<right)
        {
            if(stock[i]<key)
            {
                swap(stock[++left],stock[i++]);
            }
            else if(key == stock[i])
            {
                i++;
            }
            else
            {
                swap(stock[--right],stock[i]);
            }
        }
        int a = left - l + 1;
        int b = right - 1 - left; 
        if(a>=k)
        {
            qsort(stock,l,left,k);
        }
        else if(a+b>=k)
        {
            return;
        }
        else
        {
            qsort(stock,right,r,k-a-b);
        }
    }
    int getRand(vector<int>& stock, int left ,int right)
    {
        int r = rand();
        return stock[r%(right - left + 1) + left];
    }
};
相关推荐
BlackQid7 分钟前
基于C的二分查找和查月份天数小程序
算法·c
YF云飞10 分钟前
CVPR2019 Oral论文《Side Window Filtering》解读及算法 Python 实现
python·算法·计算机视觉
楼田莉子1 小时前
C++算法学习专题:前缀和
c++·学习·算法·leetcode·蓝桥杯
data myth1 小时前
洛谷p2392kkksc03考前临时抱佛脚 详解(回溯,深度搜索法)
算法
PPIO派欧云2 小时前
从套壳生态到上下文工程:一文看懂2025年Agent六大最新趋势
算法
Ka1Yan2 小时前
[算法] 双指针:本质是“分治思维“——从基础原理到实战的深度解析
java·开发语言·数据结构·算法·面试
freexyn2 小时前
Matlab自学笔记六十六:求解带参数的不等式
算法·matlab·参数方程·编程实例·解不等式
DjangoJason2 小时前
每日算法题【二叉树】:二叉树的最大深度、翻转二叉树、平衡二叉树
数据结构·算法·链表
CoovallyAIHub4 小时前
GQNN 框架:让 Python 开发者轻松搭建量子神经网络
深度学习·算法·计算机视觉
CoovallyAIHub4 小时前
轻量级注意力模型HOTSPOT-YOLO:无人机光伏热异常检测新SOTA,mAP高达90.8%
深度学习·算法·计算机视觉