【刷题11】分治—快速排序

目录

一、排序数组

题目:

思路:快速排序(三路划分)

  • 交换、三数取中(设置随机数,让mid更随机些)
  • 三路划分:因为数组里面可能有多个相同的数,如果全是一样的数,就影响了快排的效率

代码:

cpp 复制代码
class Solution {
public:
    int getMid(vector<int>& nums, int left, int right)
    {
        int mid = left + (rand() % (right-left));
        return mid;
    }
    // 快速排序
    void QuickSort(vector<int> &nums, int left, int right)
    {
        if(left >= right) return;
        int mid = getMid(nums, left, right);
        swap(nums[mid], nums[left]);
        int k = nums[left];
        int begin = left, end = right, cur = left;
        while(cur <= right)
        {
            if(nums[cur] < k) 
            {
                swap(nums[cur], nums[left]);
                ++cur;
                ++left;
            }
            else if(nums[cur] > k)
            {
                swap(nums[cur], nums[right]);
                --right;
            }
            else ++cur;
        } 
        QuickSort(nums, begin, left-1);
        QuickSort(nums, right+1, end);
    }
    vector<int> sortArray(vector<int>& nums) {
        srand(time(0));
        int n = nums.size();
        QuickSort(nums, 0, n-1);
        return nums;
    }
};

二、颜色分类

题目:

思路:与上题一样

代码:

cpp 复制代码
class Solution {
public:
    int getMid(vector<int> &nums, int left ,int right)
    {
        int mid = left + (rand() % (right-left));
        return mid;
    }
    void QuickSort(vector<int> &nums, int left, int right)
    {
        if(left >= right) return;
        int n=nums.size();
        int mid = getMid(nums, left, right);
        swap(nums[mid], nums[left]);
        int k = nums[left];  
        int begin = left, end = right, cur = left;
        while(cur <= right)
        {
            if(nums[cur] < k)
            {
                swap(nums[cur], nums[left]);
                cur++;
                left++;
            }
            else if(nums[cur] > k)
            {
                swap(nums[cur], nums[right]);
                right--;
            }
            else cur++;
        }        
        QuickSort(nums, begin, left-1);
        QuickSort(nums, right+1, end);
    }
    void sortColors(vector<int>& nums) {
        srand(time(0));
        QuickSort(nums, 0, nums.size()-1);
    }
};

另一种写法:

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

三、数组中第k个最大元素

题目:

思路:

  • 分三块与前面两题相同
  • a,b,c是每块区间的元素个数
  • c大于等于k:第k大在右边的区间,去右边的区间找
  • b+c大于等于k:排除了在右边,那么一定在中间的区间,该区间的元素都是一样的,所以直接返回key
  • 前面两个不成立,去左边的区间找,因为第k大是相对于整个数组的,而中间的和右边的区间已经确定了(第k大不会出现在中间和右边),所以k要减去中间和右边区间的个数

代码:

cpp 复制代码
class Solution {
public:
    int getMid(vector<int> &nums, int left, int right)
    {
        int mid = left + (rand() % (right-left));
        return nums[mid];
    }
    int qsort(vector<int>& nums, int l, int r, int k)
    {
        if(l >= r) return nums[l];///
        int key = getMid(nums, l, r);
        int left = l, right = r, cur = l;
        while(cur <= right)
        {
            if(nums[cur] < key)
            {
                swap(nums[cur], nums[left]);
                left++;
                cur++;
            }
            else if(nums[cur] > key)
            {
                swap(nums[cur], nums[right]);
                right--;
            }
            else cur++;
        }
        int b = right-left+1;
        int c = r - right;
        if(c >= k) return qsort(nums, right+1, r, k);
        else if(b+c >= k) return key;
        else return qsort(nums, l, left-1, k-b-c);
    }
    int findKthLargest(vector<int>& nums, int k) {
        srand(time(0));
        int ret = qsort(nums, 0, nums.size()-1, k);
        return ret;
    }
};

解法二:堆

思路:建立一个小堆,先放k个元素,然后遍历剩余的元素,只要比堆顶大就进堆,往下沉。最后的堆顶就是第k大的元素

代码:

cpp 复制代码
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int n = nums.size();
        priority_queue<int, vector<int>, greater<int>> pq(nums.begin(), nums.begin()+k);
        for(int i=k; i<n;i++)//从k开始,不能重复比较
        {
            if(nums[i] > pq.top())
            {
                pq.pop();
                pq.push(nums[i]);
            }
        }
        return pq.top();
    }
};

四、库存管理lll

题目:

思路:快速排序---与前面相同,最后返回前cnt个元素

代码:

cpp 复制代码
class Solution {
public:
    int getMid(vector<int>& nums, int left, int right)
    {
        int mid = left+(rand()%(right-left));
        return nums[mid];
    }
    void qsort(vector<int>& nums, int l, int r)
    {
        if(l >= r) return;
        int key = getMid(nums, l, r);
        int left = l, right = r, cur = l;
        while(cur <= right)
        {
            if(nums[cur] < key) 
            {
                swap(nums[cur++], nums[left++]);
            }
            else if(nums[cur] > key) 
            {
                swap(nums[cur], nums[right--]);
            }
            else cur++;
        }
        qsort(nums, l, left-1);
        qsort(nums, right+1, r);
    }
    vector<int> inventoryManagement(vector<int>& stock, int cnt) {
        srand(time(0));
        qsort(stock, 0, stock.size()-1);
        vector<int> ret;
        for(int i=0;i<cnt;i++) ret.push_back(stock[i]);
        return ret;
    }
};
相关推荐
鹿角片ljp2 分钟前
Prompt Cache、Token 成本与 Plan Compiler 的工程设计
java·python·算法
郝学胜-神的一滴3 分钟前
C++20模板元编程 05:吃透变参模板,解锁编译期万能参数能力
服务器·开发语言·c++·windows·vscode
萧西待水7 小时前
奥赛一本通 1447 靶形数独
算法·深度优先
梦帮科技9 小时前
AI 音乐产品的发布工程:验证门、数据发布、回滚与生产运维纪律
数据结构·数据库·架构·node.js·音视频·动态规划·推荐算法
泯泷9 小时前
那段文字是谁删的?Yjs 14 正式版之前,一套删除归属方案的实现与边界
前端·javascript·算法
hold?fish:palm9 小时前
34 合并K个升序链表
javascript·算法·链表
C++ 老炮儿的技术栈9 小时前
我们在设计tcp协议时,要传一个字符串过去,报文:头十长度十内容,是否要把‘\0‘也填入,长度是否包含‘\0‘
开发语言·数据结构·c++·mfc·c
Navigator_Z11 小时前
LeetCode //C - 1252. Cells with Odd Values in a Matrix
c语言·算法·leetcode
语戚12 小时前
力扣 1621. 大小为K的不重叠线段的数目:动态规划(Java 实现)
java·算法·leetcode·动态规划·力扣·dp
青山木13 小时前
Hot 100 --- 最长有效括号
java·数据结构·算法·leetcode·动态规划