LC.75 | 颜色分类 | 数组 | 三指针

输入: 数组 nums,元素只包含 0(红)、1(白)、2(蓝)。

要求: 在原地对 nums 排序,相同颜色相邻,顺序为红(0)、白(1)、蓝(2),不能使用 sort。

输出: 排序后的数组 。

思路1:两次双指针处理,第一次处理0与非0元素,得到0与非0的分界点,再处理剩余元素中的1与2。

思路2:空间换时间,一次遍历,分三组,但是要求原地排序,那没事了,不可行。

思路3:

  • 0指针从序号0开始,记录下一个0元素要放在哪里

  • 2指针从序号n-1开始,记录下一个2元素放在哪里

  • 遍历指针,从头遍历到位,且遍历指针不大于2指针。

  • 从头开始遍历数组,找到第一个非0元素,令该位置为0指针起点

  • 从尾开始遍历数组,找到第一个非2元素,令该位置为2指针起点

  • 从0指针起点开始遍历数组,循环范围 小于等于 2指针序号

  • 开始遍历,遇0就跟0指针交换,0指针进1;遇2就跟2指针交换,2指针减1,而且得检查2指针交换回来的数是什么。

思路4:三指针法

  • 定义指针:

    • p0:指向下一个 0 应放置的位置;

    • curr:当前遍历位置;

    • p2:指向下一个 2 应放置的位置。

  • 循环条件:curr <= p2。

  • 规则:

    • 若 nums[curr] == 0 → 与 nums[p0] 交换,p0++,curr++。

    • 若 nums[curr] == 2 → 与 nums[p2] 交换,p2--,curr 不动。

    • 若 nums[curr] == 1 → curr++。

时间复杂度:O(n),空间复杂度:O(1)。

class Solution { 
public: 
    void sortColors(vector<int>& nums) { 
        int n = nums.size(); 
        int p0 = 0; 
        while (p0 < n && nums[p0] == 0) { 
            p0++; 
        } 
        if (p0 >= n) { 
            return; 
        } 
        int p2 = n - 1; 
        while (p2 >= 0 && nums[p2] == 2) { 
            p2--; 
        } 
        if (p2 <= 0) { 
            return; 
        } 
        for (int i = p0; i <= p2; i++) { 
            if (nums[i] == 0) { 
                nums[i] = nums[p0]; 
                nums[p0++] = 0; 
            } 
            else if (nums[i] == 2) { 
                nums[i] = nums[p2]; 
                nums[p2--] = 2; 
                i--;
            } 
        } 
        return; 
    } 
};
class Solution {
public:
    void sortColors(vector<int>& nums) {
        int n = nums.size();
        int p0 = 0;
        int p1 = p0;
        int p2 = n -1;
        while (p1 <= p2) {
            if (nums[p1] == 0) {
                swap(nums[p0++], nums[p1++]);
            }
            else if (nums[p1] == 1) {
                p1++;
            }
            else if (nums[p1] == 2) {
                swap(nums[p2--], nums[p1]);
            }
        }
        return;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值