三色旗问题详解(两种高效优雅的 实现方式)

这篇博客探讨了LeetCode 75题的解决方案,即对包含红、白、蓝三种颜色的数组进行排序。文章详细介绍了两种使用双指针策略的排序算法,通过不断移动指针来划分数组区间,实现颜色的有序排列。此外,还提出了将这种方法推广到任意pivot值的排序情况。
摘要由CSDN通过智能技术生成

leetcode 75
给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

对这道题进一步的进行推广,在数组中任意选择一个数pivot,将比pivot小的数在左边,比pivot大的数在右边,等于pivot载中间,举例:[3,4,4,2,7,9] 将pivot = 4,排序之后的结果就是[3,2,4,4,7,9]

第一种方式解决方式

代码的思路:(注意是开区间,还是闭区间)
初始情况:front = -1, rear = n, 分别是小于pivot,和大于pivot的区间分界点的指针,cur = 0 待处理的元素指针
数组空间划分成四部分 [0,front] 小于pivot , [rear,n-1]区间大于pivot在(cur,rear)这个区间待处理的数据,(front,cur)等于pivot区间;

操作:
情况一:nums[cur] == pivot,直接cur++;
情况二:nums[cur] < pivot, 交换数组front+1和cur的位置,front++,cur++
情况三:nums[cur] > pivot 交换数组rear-1和cur的位置,rear–(注意cur此时是不变了的,这是因为 交换过来的元素还没有判断过)

判断的结束条件:cur和rear指针相遇

private void sortArrayByKey (int[] nums,int key) {
        int front = -1,rear = nums.length;
        int cur = 0;
        while(cur < rear){
            if(nums[cur] < key) {
                swap(nums,++front,cur++);
            } else if(nums[cur] > key) {
                swap(nums,--rear,cur);
            } else {
                cur++;   
            }
        }
    }

第二种方式 其实实现逻辑也是通过指针划分区间的方式实现(弄清指针的含义,问题就解决一半了)

  1. 指针p1小于最右pivot的位置
  2. 指针p2指向小于等于最右pivot的位置
  3. 指针指向cur的大于pivot最右侧的一个指针

初始化 p1 = -1,p2 = -1,cur = 0,其实区间都是没有元素的
情况一:nums[cur] > pivot时,cur++;
情况二 :nums[cur] <= pivot, 将p2 + 1的位置和cur交换位置,p2++;
接着判断 nums[p2] < pivot成立,继续交换p1 + 1 和p2的位置,然后更新p1++;

private void sortArrayByPivotV2(int[] nums,int pivot) {
        int p1 = -1,p2 = -1;
        int cur = 0;
        while(cur < nums.length) {
            if(nums[cur] <= pivot){
                swap(nums,++p2,cur);
                if(nums[p2] < pivot) {
                    swap(nums,++p1,p2);
                }
            }
            //当前元素大于pivot的时候如何处理呢? 什么也不做,只是更新cur下表
            cur++;
        }
    }

欢迎小伙伴 评论区交流!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值