题目描述:
给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
必须在不使用库内置的 sort 函数的情况下解决这个问题。
解题思路:
思路1:排序法(利用数据特性)
在本题目中我们可以发现一个数据特性*我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。*而且题目最终是要我们将数组按照从小到大的顺序排序,所以我们按照题目要求选择一个用的较多的原地排序算法–快速排序算法对数组进行排序。
代码:
class Solution {
public void sortColors(int[] nums) {
quickSort(nums, nums.length);
}
public void quickSort(int[] a, int n) {
quickSortInternally(a,0,n-1);
}
//快速排序递归函数,其中p,r为下标
private void quickSortInternally(int[] a, int p, int r) {
//递归退出条件
if (p >= r) return;
int q = partition(a,p,r); //获取分区点
quickSortInternally(a,p,q-1);
quickSortInternally(a,q+1,r);
}
//获取分区点函数
private int partition(int[] a, int p, int r) {
int pivot = a[r]; //一般选取数组中最后一个作为pivot
int i = p;
for (int j = p; j < r; ++j) {
if (a[j] < pivot) {
if (i == j) {
++i;
} else {
int tmp = a[i];
a[i++] = a[j];
a[j] = tmp;
}
}
}
int tmp = a[i];
a[i] = a[r];
a[r] = tmp;
return i;
}
}
思路2:双指针法
如果我们将题目更加一般化(即我们不用一组升序的数来表示颜色或者最后我们也不按照升序还是降序的规律来排列颜色)显然,此时排序法就行不通了。但是此时我们应该发现本题目是属于数组类算法题目,而且本题目还有一个更一般的特性:
使相同元素相邻
利用这个输出特性,我们可以使用双指针法,具体操作如下:
1.定义指针p0指向数组基地址,循环遍历数组,当遍历到的元素值为"0"时交换p0位置的元素和下标为i的元素(假设此时遍历数组到下标为i的位置),p0指针自增
2.第一个循环结束后,定义指针p1指向p0,再从p1位置遍历数组,若遍历到的元素为"1"则进行课1.中一样的操作
代码:
class Solution {
public void sortColors(int[] nums) {
int p0 = 0;
for (int i = 0; i < nums.length; ++i) {
if (nums[i] == 0) {
int temp = nums[0];
nums[p0] = nums[i];
nums[i] = temp;
p0++;
}
}
int p1 = p0;
for (int j = p0; j < nums.length; ++j) {
if (nums[j] == 1) {
int temp = nums[p1];
nums[p1] = nums[j];
nums[j] = temp;
p1++;
}
}
}
}