【Leetcode每日一题】 分治 - 排序数组(难度⭐⭐)(60)

1. 题目解析

题目链接:912. 排序数组

这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。

2.算法原理

算法思路:

快速排序作为一种经典的排序算法,其核心思想在于通过“分而治之”的策略,将数据划分为不同的部分,并递归地对这些部分进行排序。其中,最关键的步骤是Partition(分区),即按照某个基准元素将数组划分为左右两部分,左侧元素小于基准,右侧元素大于基准。

在处理含有大量重复元素的数据集时,常规的快速排序算法效率可能会受到影响。因此,我们可以借鉴“荷兰国旗问题”的解决思路,将数组进一步细分为左、中、右三部分:左侧存放小于基准的元素,中间存放与基准相等的元素,右侧存放大于基准的元素。随后,我们只需对左侧和右侧的元素进行递归排序,而无需处理中间的大量重复元素,从而显著提高算法效率。

算法流程:

  1. 定义递归出口
    • 当待排序的数组区间长度小于等于1时,认为该区间已排序完成,无需继续处理。
  2. 随机选择基准元素
    • 为了避免最坏情况的发生(如数组已部分有序或完全有序),我们采用随机选择基准元素的方法。
    • 初始化一个随机数生成器,生成一个随机数。
    • 将随机数转换为数组下标,通过取模运算和加上区间左边界的方式,确保下标在待排序区间的范围内。
    • 使用该下标对应的元素作为基准元素。
  3. 利用荷兰国旗思想划分数组
    • 初始化三个指针:left、mid、right,分别指向区间的最左端、最右端以及当前遍历的位置。
    • 从left开始遍历数组,根据当前元素与基准元素的大小关系,移动left、mid、right指针,并将元素交换到正确的位置。
    • 遍历结束后,数组被划分为左、中、右三部分。
  4. 递归处理左边区域和右边区域
    • 对左边区域(小于基准元素的部分)递归调用快速排序算法。
    • 对右边区域(大于基准元素的部分)递归调用快速排序算法。
    • 注意,中间与基准相等的部分无需处理,因为它们已经处于正确的位置。

3.代码编写

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 key = getRandom(nums, l, r);
        
        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]);
        }
        // [l, left] [left + 1, right - 1] [right, r]
        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];
    }
};

The Last

嗯,就是这样啦,文章到这里就结束啦,真心感谢你花时间来读。

觉得有点收获的话,不妨给我点个吧!

如果发现文章有啥漏洞或错误的地方,欢迎私信我或者在评论里提醒一声~ 

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-22 16:52:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-22 16:52:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-22 16:52:02       82 阅读
  4. Python语言-面向对象

    2024-04-22 16:52:02       91 阅读

热门阅读

  1. 聚类与分类的区别

    2024-04-22 16:52:02       122 阅读
  2. 【运维基础一】 Linux Centos 常用命令

    2024-04-22 16:52:02       89 阅读
  3. https通信流程

    2024-04-22 16:52:02       189 阅读
  4. 「Python大数据」数据采集-某东产品数据评论获取

    2024-04-22 16:52:02       29 阅读
  5. python 绘图

    2024-04-22 16:52:02       34 阅读
  6. 1、MATLAB介绍

    2024-04-22 16:52:02       31 阅读
  7. vue封装websocket以及心跳检测、重连

    2024-04-22 16:52:02       35 阅读
  8. C# 斜杠与反斜杠以及它们在路径中的使用

    2024-04-22 16:52:02       37 阅读
  9. [c++][netcdf]通过c\c++读取字段的scale_factor与add_offset

    2024-04-22 16:52:02       28 阅读