颜色分类

颜色分类(双指针排序)

(对应leetcode75题)

题目描述

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

示例:

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]

思路

利用双指针,分别指向数组的头部和尾部。因为数组中元素只有0、1、2三种情况,遍历数组,如果遍历到0,则让其与头部指针指向的元素交换位置,并且指针指向下一个元素。如果遍历到1,则直接遍历下一个元素。如果遍历到2,让其与尾部指针指向的元素交换位置,并且指针指向上一个元素(注意此时并不继续遍历下一个元素。因为如果后边的元素有1的话,那么没有交换元素,继续遍历导致2在1前面。所以只能继续遍历当前元素,尾部指针向前移动,直到交换来的元素是0或1时再向下遍历。)

代码块

class Solution {
    public void sortColors(int[] nums) {
        int i=0, j = nums.length - 1;  //定义双指针
        int count = 0;  //遍历数组计数器
        while(count <= j){   //当计数器超过后指针说明已将所有数字归位
            if(nums[count] == 0){   //当前数字为0时和i指针数字进行交换,计数器+1
                swap(nums, count, i);
                i++;   //i指针右移
                count++;
            }else if(nums[count] == 2){//当前数字为2时和j指针数字交换
                swap(nums, count, j);
                j--;  //j指针左移
                /*计数器不能+1, 若交换来的nums[count]仍是2的话,假设计数器+1, 后面的数字也都是1,这个数字2
                就会卡在这里,因为此时循环已经跳出,造成结果错误,所以必须等到交换来的新nums[count]不是2(即1
                或0时计数器才能+1)*/

            }else{
                count++;
            }
        }
    }

    public void swap(int [] nums, int i, int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

举例

数组:[0,2,1,2,0,2,1]
1、两个指针i,j,i指向第一个元素0,j指向最后一个元素1。
2、遍历元素,计数器count = 0。第一个元素0,所以执行

if(nums[count] == 0){   //当前数字为0时和i指针数字进行交换,计数器+1
                swap(nums, count, i);
                i++;   //i指针右移
                count++;

自己跟自己交换,之后,i= 1,也就是头部指针指向第二个元素,count = 1;
3、第二个元素2,执行

else if(nums[count] == 2){//当前数字为2时和j指针数字交换
                swap(nums, count, j);
                j--;  //j指针左移

2与最后一个元素1交换,此时count= 1,j指向倒数第二个元素2。数组变为[0,1,1,2,0,2,2]
4、仍然遍历第二个元素,是1,于是count++
5、遍历第三个元素,是1,count++
6、遍历第四个元素,是2,于是与尾部指针所指向的元素2交换,数组保持不变,但是尾部指针指向倒数第三个元素0
7、仍然遍历第四个元素,2与0交换,于是数组变为[0,1,1,0,2,2,2],第四个元素变为0,于是0与头部指针指向的第二个元素1互换,数组变为[0,0,1,1,2,2,2]
8、此时遍历到第五个元素,后指针指向倒数第四个元素,因为当计数器超过后指针,循环结束。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值