难度:中等
给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
必须在不使用库的sort函数的情况下解决这个问题。
题目链接
java实现
插入排序
/**
* 插入排序
* --有序区 无序区
* --从有序区中找到待插入元素的位置
*
* @param nums
*/
public void sortColors(int[] nums) {
if (nums == null || nums.length == 0) {
new IllegalArgumentException("nums is empty!");
}
for (int i = 1; i < nums.length; i++) {
int num = nums[i];
// i索引之前的就是有序区
for (int j = 0; j < i; j++) {
if (nums[j] > num) {
for (int k = i - 1; k >= j; k--) {
nums[k + 1] = nums[k];
}
nums[j] = num;
break;
}
}
}
}
计数排序(统计每个元素出现的次数)
计数排序
// 计数排序(统计每个元素出现的次数)
public void sortColors2(int[] nums) {
if (nums == null || nums.length == 0) {
new IllegalArgumentException("nums is empty!");
}
int zeroNums = 0, oneNums = 0, twoNums = 0;
for (int i = 0; i < nums.length; i++) {
int num = nums[i];
if (num == 0) {
zeroNums++;
} else if (num == 1) {
oneNums++;
} else if (num == 2) {
twoNums++;
}
}
for (int i = 0; i < zeroNums; i++) {
nums[i] = 0;
}
for (int i = zeroNums; i < zeroNums + oneNums; i++) {
nums[i] = 1;
}
for (int i = zeroNums + oneNums; i < nums.length; i++) {
nums[i] = 2;
}
}
三路快排
// 三路快排
public void sortColors3(int[] nums) {
if (nums == null || nums.length == 0) {
new IllegalArgumentException("nums is empty!");
}
sort3Ways(nums, 0, nums.length - 1);
}
/**
* 递归操作
* 对nums数组从[left...right]区域进行3路快排排序
*
* @param nums array
* @param left 左边界
* @param right 右边界
*/
private void sort3Ways(int[] nums, int left, int right) {
// 递归到底的情况
if (left >= right) {
return;
}
// 递归操作
// 基准元素
int v = nums[left];
// 操作元素的索引
int i = left + 1;
int lt = left; // 注意
int gt = right + 1;
for (; i <= right && i < gt; i++) {
int num = nums[i];
if (num == v) {
continue;
} else if (num < v) {
swap(nums, i, lt + 1);
lt++;
} else {
swap(nums, i, gt - 1);
gt--;
i--;
}
}
swap(nums, lt, left);
sort3Ways(nums, left, lt - 1);
sort3Ways(nums, gt, right);
}
private void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}