leetcode算法-颜色分类-75

该博客主要介绍了如何解决LeetCode中的颜色分类问题。通过分析题目,博主提出了一个进阶解法,在空间复杂度为O(n)的情况下,利用一趟扫描完成数组中红、白、蓝元素的排序。具体策略是移动0和2到正确位置,保证1自动到达中间。通过设置next0和next2变量,遍历数组并交换元素,实现了原地排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

leetcode算法-颜色分类

题目来源:leetcode传送门

题目

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

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

注意:
不能使用代码库中的排序函数来解决这道题。

示例:

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

进阶:

一个直观的解决方案是使用计数排序的两趟扫描算法。
首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
你能想出一个仅使用常数空间的一趟扫描算法吗?

解题思路

由于数组中只有0,1,2三个元素,显而易见的我们可以遍历一遍之后得出0,1,2的个数,然后再重写给当前数组赋值就可以了。但是这个方法会扫描两次数组,进阶中要求在空间复杂度为O(n)的前提下使用一趟扫描完成。

要在一趟扫描完成这个动作,我们必须在遍历的过程中移动每个元素到正确的位置。那么什么才是正确的位置呢?显而易见,开头全为0,接着全是1,剩下的全为2,这样的位置。
由于只有三个元素,我们可以只移动其中两种元素到正确的位置,则移动结束后剩余的位置即为第三种元素的位置。

那么移动哪两个比较好呢?我选的是0和2,因为一个在开头一个在结尾,容易找到移动的目标位置。我们只需要设置两个变量next0和next2,next0代表下一个0应该移动到的位置,next2代表下一个2应该移动到的位置,然后遍历数组,如果当前元素值为0或2且当前索引与next不同,则交换当前索引元素与next索引元素,然后每次移动结束后,当前索引保持不变,以保证交换后的元素也能被正确地移动,然后移动next变量到下一个位置(next0++,next2- -)。

这样遍历一遍之后,所有的0和2都会被交换到正确的位置,而剩下的自然就是1,因为我们全程都是在原地进行交换,因此1也会到正确的位置。

代码

class Solution {
    public static void sortColors(int[] nums) {
        if (nums == null || nums.length == 0)
            return;
        int len = nums.length,
        next0 = 0,//0的下一个位置
        next2 = len-1;//2的下一个位置
        for (int i = 0; i < len; i++) {
            if (nums[i] == 0 && next0<i) {
                swap(nums, i--, next0++);
            } else if (nums[i] == 2 && next2>i) {
                swap(nums, i--, next2--);
            }
        }
    }
    // 交换数组元素位置
    public static void swap(int[] nums, int i, int j) {
        if(nums[i]==nums[j])return ;
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值