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是等价的。

posted @ 2024-09-02 11:50  Gold_stein  阅读(3)  评论(0编辑  收藏  举报