题目描述:
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
示例 1:
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
示例 2:
输入:nums = [2,0,1]
输出:[0,1,2]
示例 3:
输入:nums = [0]
输出:[0]
示例 4:
输入:nums = [1]
输出:[1]
提示:
1. n == nums.length
2. 1 <= n <= 300
3. nums[i] 为 0、1 或 2
进阶:
你可以不使用代码库中的排序函数来解决这道题吗?
你能想出一个仅使用常数空间的一趟扫描算法吗?
题目分析:
这道题可以使用双指针解法使数组排序。首先定义左右指针分别指向数组头和尾。定义当前检查的标记位。遍历数组,如果当前元素为0,则应该把该元素放在数组最左边,所以我们将左指针指向的元素与当前元素交换,此时左指针指向的元素已经确定下来,右移左指针,继续检查下一个元素。如果当前元素为1,我们默认认为该元素位置是最终排序完该元素所在的位置,不移动左指针,如果后面元素存在0,再与此元素交换,继续检查下一个元素。如果当前元素为2,该元素应该放在数组的最右边,所以我们将当前元素和右指针指向的元素进行交换,交换完后右指针指向的位置元素已经确定,左移右指针,继续检查数组下一个元素。直到标记位越过右指针指向的位置,数组排完序。因为当前数组只有可能存在0,1,2这三个元素,所以我们才能用上述方法求解。
例如,假设输入nums = {2,0,2,1,1,0}。
首先让左右指针指向数组首尾,标志位指向数组首元素。首元素为2,应该放在数组最右边,交换首元素和右指针指向的元素。
交换后,右指针上的元素确定下来,左移右指针,继续检查当前标记位上的元素。
当前标记位上的元素为0,交换当前元素和左指针指向的元素。此时左指针指向的元素确定下来,右移左指针,移动标记位继续检查下一个位置上的元素。
当前标记位上的元素值还为0,交换当前元素和左指针指向的元素。此时左指针指向的元素确定下来,右移左指针,移动标记位继续检查下一个位置上的元素。
当前标记位上的元素值为2,应该放在数组右边,交换当前元素和右指针指向的元素。
右指针指向的元素值确定下来,左移右指针,检查当前标记位上的元素。元素值刚好为1,我们假设该元素位置为最终排完序的位置,继续检查下一个元素。
该元素值也为1,继续检查下一个元素。
此时标记位已经越过右指针指向的位置,说明数组已经排完序。
题解一(调用库函数):
执行用时: 0 ms
内存消耗: 36.8 MB
题解二(双指针):
执行用时: 0 ms
内存消耗: 37.1 MB
题目来源:力扣(LeetCode)