分治算法(1)_颜色分类

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

分治算法(1)_颜色分类

收录于专栏【经典算法练习
本专栏旨在分享学习算法的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

1. 分治思想简介 :

2. 题目链接 :

3. 题目描述 :

4. 解法(三指针) :

    题目分析 :

    算法思路 :

    代码展示 :

    结果分析 :


1. 分治思想简介 :

        分治思想(Divide and Conquer)是一种广泛应用于算法设计中的重要策略,其基本思想是将一个复杂的问题分解为多个较简单的子问题,递归地解决这些子问题,然后将它们的解合并为原问题的解。(分而治之)

        分治思想在很多经典算法中得到了应用,以下是几个常见的例子:

1. 归并排序(Merge Sort):将数组分为两个部分,分别进行排序,然后合并两个已排序的部分。
2. 快速排序(Quick Sort):选择一个“基准”元素,将数组划分为比基准小和大的两部分,递归排序这两部分。
3. 二分查找(Binary Search):在有序数组中查找一个元素,通过不断地将搜索范围减半来达到快速查找的目的。
4. 矩阵乘法(Strassen’s Algorithm):通过分解矩阵为子矩阵来减少乘法的复杂度。
5. 快速傅里叶变换(FFT):在信号处理和图像处理中用于高效地计算离散傅里叶变换。

        分治法的优点:

效率:通过将问题规模减小到较小的子问题,能够在较短的时间内求解复杂问题。
清晰性:分治法的递归结构使得算法逻辑更加清晰和易于理解。
适应性:许多问题可以自然地用分治法来解决,从而减少编程的复杂性。

2. 题目链接 :

OJ链接 : 颜色分类

3. 题目描述 :

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

必须在不使用库内置的 sort 函数的情况下解决这个问题。

示例 1:

输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]

示例 2:

输入:nums = [2,0,1]
输出:[0,1,2]

提示:

  • n == nums.length
  • 1 <= n <= 300
  • nums[i] 为 01 或 2

4. 解法(三指针) :

    题目分析 :

        题目要求: 给定一个包含红色、白色和蓝色、共 n个元素的组数组 nums ,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。(使用整数 0、 1 和 2 分别表示红色、白色和蓝色。)

        所以这个我们只能对原数组进行排序,不能额外创建空间,更不能直接使用库里面的sort(虽然能通过~~):

class Solution {
public:
    void sortColors(vector<int>& nums) {
        sort(nums.begin(), nums.end());
    }
};

    算法思路 :

类比数组分块的算法思想,这里是将数组分成三块,我们可以再添加一个指针,实现数组分为三块.

设数组大小为n,定义三个指针left, cur, right:

        left: 用来标记0序列的末尾,因此初始化为-1;

        cur: 用来扫描数组,初始化为0;

        right: 用来标记2序列的起始未知,因此初始化为n

在cur往后扫描的过程中,保证:

        [0, left]内的元素都是0

        [left + 1, cur - 1]内的元素都是1

        [cur, right -1] 内的元素是待定元素

        [right, n]内的元素都是2 

        所以我们在扫描的过程中有:

 1. nums[cur] == 0 : swap(nums[++left], nums[cur++])

 2. nums[cur] == 1 : cur++

 3. nums[cur] == 2 : swap(nums[--right], nums[cur])  注意这里cur不需要++,因为[cur, right - 1]是待定元素,还需要判断!

    代码展示 :

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

    结果分析 :

 时间复杂度分析:
    O(n),其中 n 是数组 nums 的长度。每个元素最多处理一次。
空间复杂度分析:
    使用的额外空间:该算法只使用了常量级别的额外空间,主要是 left、right 和 cur 三个指针,没有使用额外的数组或数据结构。因此,空间复杂度为:O(1),只使用了常数级的空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值