leetcode 75. Sort Colors & 三路快速排序
leetcode 75. Sort Colors & 三路快速排序
只有0和1的情况
在这种简化情况下,我们只需要顺序遍历数组,遇到0就放到前面即可。
class localExperiment { public: void sort01(std::vector<int> &nums) { int zero_ptr = 0; for(int i = 0; i < nums.size(); i++) { if(!nums[i]) std::swap(nums[i], nums[zero_ptr++]); } for(auto num : nums) std::cout << num << " "; std::cout << std::endl; } };
这道题的解法
这道题在0和1的基础上加入了一个2,只需要在0和1的处理逻辑之前加上处理2的逻辑即可。
class Solution { public: void sortColors(std::vector<int> &nums) { int m = nums.size(); int zero_ptr = 0, two_ptr = m - 1; for(int i = 0; i < m && i <= two_ptr; i++) { while(nums[i] == 2 && i <= two_ptr) std::swap(nums[i], nums[two_ptr--]); if(!nums[i]) std::swap(nums[i], nums[zero_ptr++]); } } };
第一个要用while,第二个仍然是if的原因:
假设我们输入的数组是
0 2 0 1 0 2 1 2
当我们的i = 1, two_ptr = 7的时候,会发生一次无效交换,导致nums[1]再也无法回到正确的位置上去了,所以这一步需要用while
又因为我们已经用while解决了2带来的无效交换问题,我们的0和1交换的部分仍然可以沿用之前的逻辑。
三路快速排序
// 模板的 T 参数表示元素的类型,此类型需要定义小于(<)运算 template <typename T> // arr 为需要被排序的数组,len 为数组长度 void quick_sort(T arr[], const int len) { if (len <= 1) return; // 随机选择基准(pivot) const T pivot = arr[rand() % len]; // i:当前操作的元素下标 // arr[0, j):存储小于 pivot 的元素 // arr[k, len):存储大于 pivot 的元素 int i = 0, j = 0, k = len; // 完成一趟三路快排,将序列分为: // 小于 pivot 的元素 | 等于 pivot 的元素 | 大于 pivot 的元素 while (i < k) { if (arr[i] < pivot) swap(arr[i++], arr[j++]); else if (pivot < arr[i]) swap(arr[i], arr[--k]); else i++; } // 递归完成对于两个子序列的快速排序 quick_sort(arr, j); quick_sort(arr + k, len - k); }
注意,当pivot < arr[i]的时候,只交换,但是i不加一,这和for循环的时候用while是等价的。