当前位置: 首页 > news >正文

【排序算法】堆排、快排、归并排、各种排

头像
⭐️个人主页:@小羊
⭐️所属专栏:算法
很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~

动图描述

目录

    • 1、堆排
    • 2、快排
      • 颜色分类
      • 排序数组
      • 数组中的第K个最大元素
      • LCR 159. 库存管理 III
    • 3、归并
      • 排序数组
      • LCR 170. 交易逆序对的总数
      • 计算右侧小于当前元素的个数
      • 翻转对


1、堆排



2、快排

颜色分类

  • 颜色分类

在这里插入图片描述

在这里插入图片描述

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int i = 0, l = -1, r = nums.size();
        while (i < r)
        {
            if (nums[i] == 0) swap(nums[++l], nums[i++]);
            else if (nums[i] == 1) i++;
            else swap(nums[--r], nums[i]);
        }
    }
};

排序数组

  • 排序数组

在这里插入图片描述

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        srand(time(nullptr));
        qsort(nums, 0, nums.size() - 1);
        return nums;
    }
    void qsort(vector<int>& nums, int l, int r)
    {
        if (l >= r) return;
        int key = nums[rand() % (r - l + 1) + l]; // 获取随机基准值
        int i = l, left = l - 1, 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);
    }
};

数组中的第K个最大元素

  • 数组中的第K个最大元素

在这里插入图片描述

最容易想到的就是优先级队列。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int> pq;
        for (auto e : nums) pq.push(e);
        int ret = 0;
        while (k--)
        {
            ret = pq.top();
            pq.pop();
        }
        return ret;
    }
};

快速选择算法

经常出错:else return qsort(arr, l, left, k - b - c);

在这里插入图片描述

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        srand(time(nullptr));
        return qsort(nums, 0, nums.size() - 1, k);
    }
    int qsort(vector<int>& arr, int l, int r, int k)
    {
        if (l >= r) return arr[l];
        int key = arr[rand() % (r - l + 1) + l]; // 随机基准值
        int i = l, left = l - 1, right = r + 1;
        // 三路划分
        while (i < right)
        {
            if (arr[i] < key) swap(arr[++left], arr[i++]);
            else if (arr[i] == key) i++;
            else swap(arr[--right], arr[i]);
        }
        // 分情况讨论
        int c = r - right + 1, b = right - left - 1;
        if (c >= k) return qsort(arr, right, r, k);
        else if (c + b >= k) return key;
        else return qsort(arr, l, left, k - b - c);
    }
};

LCR 159. 库存管理 III

  • LCR 159. 库存管理 III

在这里插入图片描述

最先想到的还是优先级队列。

class Solution {
public:
    vector<int> inventoryManagement(vector<int>& stock, int cnt) {
        priority_queue<int, vector<int>, greater<int>> pq;
        for (auto e : stock) pq.push(e);
        vector<int> ret;
        while (cnt--)
        {
            ret.push_back(pq.top());
            pq.pop();
        }
        return ret;
    }
};

快速选择算法。

我就说经常出错吧,这才几分钟…else qsort(stock, right, r, cnt - a - b);

class Solution {
public:
    vector<int> inventoryManagement(vector<int>& stock, int cnt) {
        srand(time(nullptr));
        qsort(stock, 0, stock.size() - 1, cnt);
        return { stock.begin(), stock.begin() + cnt };
    }
    void qsort(vector<int>& stock, int l, int r, int cnt)
    {
        if (l >= r) return;
        int key = stock[rand() % (r - l + 1) + l];
        int i = l, left = l - 1, right = r + 1;
        while (i < right)
        {
            if (stock[i] < key) swap(stock[++left], stock[i++]);
            else if (stock[i] == key) i++;
            else swap(stock[--right], stock[i]);
        }
        int a = left - l + 1, b = right - left - 1;
        if (a >= cnt) qsort(stock, l, left, cnt);
        else if (a + b >= cnt) return;
        else qsort(stock, right, r, cnt - a - b);
    }
};

3、归并

排序数组

  • 排序数组

在这里插入图片描述

class Solution {
    vector<int> tmp;
public:
    vector<int> sortArray(vector<int>& nums) {
        int sz = nums.size();
        tmp.resize(sz);
        MergeSort(nums, 0, sz - 1);
        return nums;
    }
    void MergeSort(vector<int>& arr, int l, int r)
    {
        if (l >= r) return;
        int mid = (l + r) >> 1;
        MergeSort(arr, l, mid);
        MergeSort(arr, mid + 1, r);
        int b1 = l, b2 = mid + 1, i = l;
        while (b1 <= mid && b2 <= r)
        {
            tmp[i++] = arr[b1] < arr[b2] ? arr[b1++] : arr[b2++];
        }
        while (b1 <= mid) tmp[i++] = arr[b1++];
        while (b2 <= r) tmp[i++] = arr[b2++];
        for (int i = l; i <= r; i++) arr[i] = tmp[i];
    }
};

LCR 170. 交易逆序对的总数

  • LCR 170. 交易逆序对的总数

在这里插入图片描述

本题要求统计逆序对总数,笼统地说就是找前一部分的数有多少个数大于后一部分的数,那么对于前一部分和后一部分来说有序和乱序都是无所谓的。

在这里插入图片描述

排升序,找cur2之前有多少个数比我大。

class Solution {
    vector<int> tmp;
public:
    int reversePairs(vector<int>& record) {
        int sz = record.size();
        tmp.resize(sz);
        return MergeSort(record, 0, sz - 1);
    }
    int MergeSort(vector<int>& arr, int l, int r)
    {
        if (l >= r) return 0;
        int mid = (l + r) >> 1;
        int ret = 0; // 逆序对个数
        ret += MergeSort(arr, l, mid);
        ret += MergeSort(arr, mid + 1, r);
        int b1 = l, b2 = mid + 1, i = l;
        while (b1 <= mid && b2 <= r)
        {
            // 拍升序,找b2之前有多少个数比我大
            if (arr[b1] <= arr[b2]) tmp[i++] = arr[b1++];
            else
            {
                tmp[i++] = arr[b2++];
                ret += mid - b1 + 1;
            }
        }
        while (b1 <= mid) tmp[i++] = arr[b1++];
        while (b2 <= r) tmp[i++] = arr[b2++];
        for (int i = l; i <= r; i++) arr[i] = tmp[i];
        return ret;
    }
};

在这里插入图片描述

排降序,找cur1之后有多少个数比我小。

class Solution {
    vector<int> tmp;
public:
    int reversePairs(vector<int>& record) {
        int sz = record.size();
        tmp.resize(sz);
        return MergeSort(record, 0, sz - 1);
    }
    int MergeSort(vector<int>& arr, int l, int r)
    {
        if (l >= r) return 0;
        int mid = (l + r) >> 1;
        int ret = 0; // 逆序对个数
        ret += MergeSort(arr, l, mid);
        ret += MergeSort(arr, mid + 1, r);
        int b1 = l, b2 = mid + 1, i = l;
        while (b1 <= mid && b2 <= r)
        {
            // 排降序,找b1之后有多少个数比我小
            if (arr[b1] <= arr[b2]) tmp[i++] = arr[b2++];
            else
            {
                tmp[i++] = arr[b1++];
                ret += r - b2 + 1;
            }
        }
        while (b1 <= mid) tmp[i++] = arr[b1++];
        while (b2 <= r) tmp[i++] = arr[b2++];
        for (int i = l; i <= r; i++) arr[i] = tmp[i];
        return ret;
    }
};

计算右侧小于当前元素的个数

  • 计算右侧小于当前元素的个数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
    vector<int> ret;
    vector<int> index; // 绑定元素和其下标
    vector<int> tmp;
    vector<int> tmpindex;
public:
    vector<int> countSmaller(vector<int>& nums) {
        int n = nums.size();
        ret.resize(n);
        index.resize(n);
        tmp.resize(n);
        tmpindex.resize(n);
        for (int i = 0; i < n; i++) index[i] = i;
        MergeSort(nums, 0, n - 1);
        return ret;
    }
    void MergeSort(vector<int>& arr, int l, int r)
    {
        if (l >= r) return;
        int mid = (l + r) >> 1;
        MergeSort(arr, l, mid);
        MergeSort(arr, mid + 1, r);
        int b1 = l, b2 = mid + 1, i = l;
        while (b1 <= mid && b2 <= r)
        {
            if (arr[b1] <= arr[b2]) 
            {
                tmp[i] = arr[b2];
                tmpindex[i++] = index[b2++]; // 下标和元素同步移动
            }
            else
            {
                ret[index[b1]] += r - b2 + 1;
                tmp[i] = arr[b1];
                tmpindex[i++] = index[b1++];
            }
        }
        while (b1 <= mid)
        {
            tmp[i] = arr[b1];
            tmpindex[i++] = index[b1++];
        }
        while (b2 <= r)
        {
            tmp[i] = arr[b2];
            tmpindex[i++] = index[b2++];
        }
        for (int i = l; i <= r; i++)
        {
            arr[i] = tmp[i];
            index[i] = tmpindex[i];
        }
    }
};

翻转对

  • 翻转对

在这里插入图片描述

在这里插入图片描述

class Solution {
    vector<int> tmp;
public:
    int reversePairs(vector<int>& nums) {
        int n = nums.size();
        tmp.resize(n);
        return MergeSort(nums, 0, n - 1);
    }
    int MergeSort(vector<int>& arr, int l, int r)
    {
        if (l >= r) return 0;
        int mid = (l + r) >> 1;
        int ret = 0; // 统计翻转对个数
        ret += MergeSort(arr, l, mid);
        ret += MergeSort(arr, mid + 1, r);
        int b1 = l, b2 = mid + 1, i = l;
        // 和归并的逻辑不同,在归并之前统计
        while (b1 <= mid && b2 <= r)
        {
            if (arr[b1] / 2.0 <= arr[b2]) b2++; // 做除法,防止溢出
            else
            {
                ret += r - b2 + 1;
                b1++;
            }
        }
        b1 = l, b2 = mid + 1;
        while (b1 <= mid && b2 <= r)
            tmp[i++] = arr[b1] <= arr[b2] ? arr[b2++] : arr[b1++];
        while (b1 <= mid) tmp[i++] = arr[b1++];
        while (b2 <= r) tmp[i++] = arr[b2++];
        for (int k = l; k <= r; k++) arr[k] = tmp[k];
        return ret;
    }
};



本篇文章的分享就到这里了,如果您觉得在本文有所收获,还请留下您的三连支持哦~

头像
http://www.dtcms.com/a/108824.html

相关文章:

  • 动态规划 线性dp系列:数字三角形
  • Mysql 中数据主键类型不一样导致数据插入速度快慢问题
  • Java开发如何基于 Spring AI Alibaba 玩转 MCP:从发布、调用到 Claude Manus 集成
  • 2.5路径问题专题:LeetCode 64. 最小路径和
  • Python的三方库之Pandas(三)
  • MetaBase Mysql8.0连接不上
  • 怎么理解量子比特模型,迁移到量子计算机开始编程
  • 飞桨新一代框架3.0正式发布:加速大模型时代的技术创新与产业应用
  • AF3 OpenFoldMultimerDataset类解读
  • 洛谷题单3-P1035 [NOIP 2002 普及组] 级数求和-python-流程图重构
  • JavaScript日期对象
  • Python 编程实战:打造高效便捷的目录结构生成器
  • 踩坑ubuntu24.04 编译vtk9.3.1的安卓版本
  • 前端开发技术演进与就业现实:顺应时代方能不被淘汰-优雅草卓伊凡
  • ubantu执行sudo chown -R username xxx(文件夹)命令失效
  • 推荐系统(二十一):基于MaskNet的商品推荐CTR模型实现
  • OpenCV 图形API(12)用于计算图像或矩阵的平均值函数mean()
  • dify开启多租户模式
  • Coco-AI 支持嵌入,让你的网站拥有 AI 搜索力
  • 基于javaweb的SSM+Maven机房管理系统设计与实现(源码+文档+部署讲解)
  • 智慧高炉厂可视化:钢铁行业的数字化转型之路
  • leetcode31.下一个排列
  • 42.C++11-右值引用与移动语义/完美转发
  • Real-Time Anomaly Detection of Network Traffic Basedon CNN
  • 动、静态创建任务
  • 实战打靶集锦-37-Wpwnvm
  • GUI-Guider 按钮按下 选项卡 右移动一个,到最右边停下
  • BMS电池关键参数及其含义
  • Lua中debug调试函数详解
  • 【DLI】Generative AI with Diffusion Models通关秘籍