分治算法---快排

一、快排的概念

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

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 小时前
运动控制教学——5分钟学会样条曲线算法!(三次样条曲线,B样条曲线)
c++·人工智能·算法·机器学习·matlab·贪心算法·机器人
小镇学者2 小时前
【NOI】在信奥赛中 什么是函数交互题?
算法
未知陨落2 小时前
LeetCode:62.N皇后
算法·leetcode
myw0712053 小时前
Leetcode94.二叉数的中序遍历练习
c语言·数据结构·笔记·算法
songx_993 小时前
leetcode(填充每个节点的下一个右侧节点指针 II)
java·数据结构·算法·leetcode
chenyuhao20243 小时前
vector深度求索(上)实用篇
开发语言·数据结构·c++·后端·算法·类和对象
minstbe4 小时前
半导体数据分析:GPR算法小白入门(三) 晶体管I-V特性仿真教程
算法
未知陨落4 小时前
LeetCode:60.单词搜索
算法·leetcode
mmz12075 小时前
动态规划 练习(c++)
c++·算法·动态规划
tqs_123455 小时前
分sheet写入excel
开发语言·python·算法