前言:
如果说代码有灵魂,那么它的灵魂一定是算法,因此,想要写出优美的程序,核心算法是必不可少的,少年,你渴望力量吗,想掌握程序的灵魂吗❓❗️那么就必须踏上这样一条漫长的道路,我们要做的,就是斩妖除魔,打怪升级!当然切记不可走火入魔,每日打怪,拾取经验,终能成圣!开启我们今天的斩妖之旅吧!✈️✈️
题目:
给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
必须在不使用库内置的 sort 函数的情况下解决这个问题。
示例:
提示:
- n == nums.length
- 1 <= n <= 300
- nums[i] 为 0、1 或 2
思路:
这题要求我们将三种颜色排好序,其实也就是对0,1,2的划分而已,如果你看了我前面写的题目的话,有一题 移动0 与这题很类似,都是类似于快排操作的实现,只不过在这里多了一个区间而已。
其实解决这题我们可以仿照解决移动0的问题,移动0使用双指针解决,这题有三种数据类型,我们可以多加一个指针,三指针来解决。
1、首先,我们可以将数据分为3个区间,左中右,左边放0,中间放1,右边放2,用指针left指向最后一个被遍历到的0元素,指针right指向最后一个被遍历到的2元素,指针i用来遍历数组(左右区间划分ok了,中间的1也就ok了)
2、left最开始指向-1,当i遍历到的元素为0时,先++left,在交换他俩的元素,i再自增。right最开始指向最后一个元素的下一个位置,如果i遍历到的值为2,则先–right再交换他俩元素,这里我们不能将i自增,因为这个时候不确定交换过后的元素是否为0,还需要再判断。
3、最后,当i指针与right指针相遇了,right往后全是2元素,所以这个时候循环就结束了。
代码实现:
class Solution {
public:
void sortColors(vector<int>& nums) {
int n = nums.size();
int left = -1, right = n, i = 0;
while(i < right)//不结束一直循环
{
if(nums[i] == 0) swap(nums[++left], nums[i++]);//由i值判断当前该如何处理,是用左指针还是右指针
else if(nums[i] == 1) ++i;
else swap(nums[--right], nums[i]);
}
}
};
这题被标为了中等,还是有一定难度的,但是如果你很熟悉快排的过程那么这题对你来说就是小case了,因为这题其实就是以1为基准值,0甩到左边,2甩到右边,很多东西都是融汇贯通的。