题目来源于LeetCode。
最简单的方法是两趟的,但是如果要求一趟完成,那么这道题的解法是和三路快速排序的做法是一模一样的。
在三路快速排序中,我们维护三个指针left
, i
, right
使得对于数组nums
的区间[START...END]
满足:
nums[START, left) < PIVOT
nums[left, i) == PIVOT
nums(right, RIGHT] > PIVOT
初始时i = left = START
,right = RIGHT
。
在这道题里面,我们的PIVOT是1,把所有比PIVOT小的(0)放在PIVOT的左边,所有比PIVOT大的(2)放在PIVOT的右边。代码很简洁,如下:
class Solution {
public void sortColors(int[] nums) {
int left = 0, right = nums.length - 1;
// nums[0, left) == 0
// nums[left, i) == 1
// nums(right, n - 1] == 2
int i = 0;
while (i <= right) {
if (nums[i] == 0) swap(nums, i++, left++); // nums[left] now is 0, nums[i] now is 1, move i
else if (nums[i] == 2) swap(nums, i, right--); // nums[right] now is 2, next loop we still check nums[i]
else i++;
}
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp;
}
}
上述解法的时间复杂度是O(N),因为可以注意到每次循环后区间[i, right)的长度(即未知元素的个数)都会减小1。