分治算法---快排

一、快排的概念

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

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];
    }
};
相关推荐
逆境不可逃1 小时前
LeetCode 双题:415. 字符串相加与 143. 重排链表
算法
2601_950760791 小时前
TNF-α:自身免疫疾病治疗的核心靶点与信号通路解析
人工智能·算法·蛋白
不会代码的小猴1 小时前
2. 了解Qt
开发语言·c++·笔记·qt·算法
比奇堡裤头村1 小时前
统计学习方法——支持向量机
算法·支持向量机·学习方法
程序喵大人3 小时前
【C++进阶】STL算法与函数对象 - 09 函数对象保存状态并复用规则
开发语言·c++·算法·stl·函数对象
致Great8 小时前
DeepSeek Harness插件开发实战教程:我让它自己写了一个 arXiv 搜索插件
算法
罗西的思考13 小时前
【Agent OS / AIOS】AOHP 深度解读:当 OS 开始为 Agent 而设计
人工智能·算法·机器学习
民乐团扒谱机13 小时前
【微实验】组合优化matlab实战(马科维茨投资模型):在收益与风险之间,寻找最优的人生配比
大数据·人工智能·算法·机器学习·数学建模·matlab·组合优化
Nil20814 小时前
leetcode 160相交链表
算法·leetcode·链表
迷途之人不知返15 小时前
算法系列2:滑动窗口
算法