分治算法---快排

一、快排的概念

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

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];
    }
};
相关推荐
飞Link1 小时前
什么是 PX4?一文了解 PX4 在空地协同中的作用
算法·无人机
一去不复返的通信er8 小时前
力扣-图论-岛屿数量
算法·leetcode·图论
程序 代码狂人10 小时前
切片表与分区表的区别(数据开发面试版)
java·大数据·开发语言·数据仓库·算法
HDU-Dade11 小时前
【校招笔试真题】简要介绍 Self-Attention 的前沿算法
人工智能·算法
小郎君65813 小时前
Vue keep-alive 切标签后滚动位置回顶?因为 onDeactivated 里读到的 scrollTop 是 0
算法
邵奈一14 小时前
GPT-6.1 Terra速度是Sol的3倍,价格减半
算法
RaaS10014 小时前
Node.js Brotli RCE 漏洞自查指南:fetch、undici、axios 都在影响面,三分钟确认你的版本
人工智能·深度学习·算法
shehuiyuelaiyuehao14 小时前
算法56,重排链表
数据结构·算法·链表
qq_4523962315 小时前
第四篇:《索引原理与实战:B-tree、Hash、GIN、GiST、BRIN》
算法·哈希算法·gin