题目
链接: link
思路(仅一趟循环判断完成)
本题要求对原地对数组中包含红色(0)、白色(1)和蓝色(2)三种颜色进行排序,不使用库函数。
解题步骤
- 分别设置两个索引 zero 和 two,保证下标 0 到 zero 对应的数组元素都为 0,下标 two 到 numsSize - 1对应的数组元素都是 2;
- 设置索引 i 用于遍历整个数组,遍历到 i 个元素的时候,保证下标 zero + 1 到 i - 1对应的数组元素都是 1;
- 当索引 i 遍历到元素 1 时,直接将元素 1 纳入到属于 1 的部分,然后继续遍历;
- 如果遍历到元素 2 时,将two 前面的索引 two - 1 对应的元素与遍历到的元素 2 交换,将元素 2 纳入到属于 2 的部分;
- 如果遍历到元素 0时,交换下标为 zero 后面的索引 zero + 1 对应的元素与遍历到的元素 0,将元素 0 纳入到属于 0 的部分。
初始的数组以及索引位置
- nums[0…zero] == 0 保证下标为 0 到 zero 对应的元素都为 0
- nums[zero+1…i-1] == 1 保证下标为 zero + 1 到 i - 1 对应的元素都为 1
- nums[two…n-1] == 2 保证下标为 two 到 n - 1 对应的元素都为 2
初始化zero为-1,two为numsSize是防止数组中不存在0或2
由于当遇到元素2时,需要把 nums[i] 与 nums[two-1] 交换,之后就需要再次判断 nums[i] ,所以再设置for循环时,不要放入i++条件,而是通过遇到元素0或元素1时再往后判断
假设第一个遇到的是 元素1
i加一,判断下一个元素
假设接着遇到的是 元素0
需要交换数组中下标为 zero+1 和下标为 i 的元素,然后在进行 i++ 判断下一个元素,而 zero 作为元素0的末尾坐标,往后加一,即zero++
假设接着遇到的是 元素2
需要交换数组中下标为 numsSize-1 和下标为 i 的元素,此时因为把 numsSize-1 的元素提到了前面,所以需要再次判断 i 下标的元素,而 two 作为元素2的起始坐标,往前加一,即 two–
代码呈现
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
void sortColors(int* nums, int numsSize){
int zero = -1;
int two = numsSize;
for (int i = 0; i < two;) {
if (nums[i] == 1) {
i++;
} else if (nums[i] == 2) {
swap(&nums[i], &nums[--two]);
} else if (nums[i] == 0) {
swap(&nums[++zero], &nums[i++]);
}
}
}
思路(冒泡)
由于只需要将数组按0.1.2的顺序排列出来,所以只需要用两趟冒泡排序将数组给排序就行,但是这种方法的适用性有些低,在元素不是升序而是乱序的时候就无法使用,所以建议使用第一种思路,但是这里还是把冒泡排序的代码给表示出来。
void swap(int* a, int* b) {
int* tmp = *a;
*a = *b;
*b = tmp;
}
void sortColors(int* nums, int numsSize) {
for (int i = 0; i < numsSize; i++) {
for (int j = i + 1; j < numsSize; j++) {
if (nums[i] > nums[j])
swap(&nums[i], &nums[j]);
}
}
}