分治算法---快排

一、快排的概念

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

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];
    }
};
相关推荐
web_Hsir1 小时前
vue3.2 前端动态分页算法
前端·算法
地平线开发者3 小时前
征程 6M 部署 Omnidet 感知模型
算法·自动驾驶
秋说3 小时前
【PTA数据结构 | C语言版】线性表循环右移
c语言·数据结构·算法
浩瀚星辰20244 小时前
图论基础算法:DFS、BFS、并查集与拓扑排序的Java实现
java·算法·深度优先·图论
oioihoii6 小时前
C++随机打乱函数:简化源码与原理深度剖析
开发语言·c++·算法
minji...7 小时前
数据结构 算法复杂度(1)
c语言·开发语言·数据结构·算法
凌肖战7 小时前
力扣网编程150题:加油站(贪心解法)
算法·leetcode·职场和发展
吃着火锅x唱着歌7 小时前
LeetCode 3306.元音辅音字符串计数2
算法·leetcode·c#
不見星空7 小时前
【leetcode】1751. 最多可以参加的会议数目 II
算法·leetcode