力扣--分治(快速排序)算法题I:颜色分类,排序数组

上篇文章:LeetCode模拟算法精解II:外观数列与数青蛙

目录

1.颜色分类

理解题意

算法原理

2.排序数组

理解题意

算法原理


1.颜色分类

https://leetcode.cn/problems/sort-colors/description/

理解题意

对整数0,1,2进行原地排序,不能使用库内置sort函数,使数组升序。

算法原理

由于需要对三个对象同时排序,所以我们使用分治的思想,如下:

在0, left中:全为0

在left+1, i - 1中:全为1

在i, right - 1中:全为等待扫描的元素

在right, n - 1中:全为2

numsi为0时,交换left和i中的元素,并且left++,i++,不过需要区分先后。

numsi为1时,i++即可。

numsi为2时,交换right和i中的元素,right--,但是i不能动,因为i存储被交换的元素,暂时还不知道其元素的内容是什么。

复制代码
class Solution {
public:
    void sortColors(vector<int>& nums) {
        int n = nums.size();   

        for(int left = -1, i = 0, right = n; i < right;)
        {
            if(nums[i] == 0) swap(nums[++left], nums[i++]);
            else if(nums[i] == 1) i++;
            else swap(nums[--right], nums[i]);
        }
    }
};

2.排序数组

https://leetcode.cn/problems/sort-an-array/description/

理解题意

在时间复杂度为o(nlog(N))的前提下,不使用内置函数,将数组变为升序排列。

算法原理

在上一题"颜色分类"中,运用了分类和快速排序的方式,在本题中,则需要在此基础上进行优化--由于时间复杂度的要求。

注意:如果想要时间复杂度接近nlog(n),那么基准元素的取值就应该是取随机值,此结论在算法导论中有所提及。

我们先随机选取一个基准元素key,在此基础上,对数组中的元素进行分类:

此后,如果numsi < key:swap(nums++left, numsi++)

如果numsi = key:i++

如果numsi > key:swap(nums--right, numsi)

而有关基准元素的选择,我们使用:r = rand();

接着,取其下标:numsr % (left - right + 1) + left,其中,r % (left - right + 1)表示为0, n - 1

代码如下:

复制代码
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];
    }
};

本章完。

相关推荐
把我格子衫拿来1 小时前
VTK 与 Qt 的 CMake 工程怎么组织?模块、工具链与二进制兼容排错
c++·qt·vtk·cmake·工程实践
总裁余(余登武)1 小时前
K-means算法改进(Python版)
python·算法·kmeans
灯澜忆梦1 小时前
【面向对象编程c++】| 指针与自定义数据类型
开发语言·c++·算法
xxwl5852 小时前
区域赛算法模版第八章---贪心(Greedy)
c++·笔记·学习·算法
雾沉川2 小时前
Visual C++运行库合集 v105.0 安装教程
开发语言·c++·dll
_wyt0012 小时前
洛谷P17461 [GESP202609 八级] 生成树计数 题解
c++·数学·树·gesp·八级·仙人掌
CCblandy2 小时前
向量检索 ANN 参数实测:换一种数据分布,recall 掉了 51 个百分点
人工智能·python·算法·自然语言处理·性能优化
CS创新实验室2 小时前
一棵树怎么做到“自平衡还不太费力“?——红黑树的旋转与染色
数据结构·算法·红黑树·408·计算机考研
Logic1012 小时前
C语言/数据结构位运算题解:异或XOR找出被挑选一次的果子编号——只出现一次的数字
c语言·数据结构·算法·数组·位运算·时间复杂度·空间复杂度
深圳市快瞳科技有限公司2 小时前
面向端侧部署的多帧宠物身份识别:完整性评分机制与工程约束
人工智能·算法·计算机视觉·端侧ai·宠物识别·宠物ai·宠物身份识别