LeetCode 数组系列 ~ 颜色分类

103 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情

概述

数组算是一个并不复杂的数据结构,但就是这个,面试官就能在面试过程中考察出很多东西来。例如经典的排序问题,二分搜索,滑动窗口等等,都是在数组这种最基础等数据结构中处理问题的。

我们做数组类算法问题的时候,常常需要定义一个变量,明确该变量的意义,并不停的维护这个变量,也需要特别注意初始值边界问题。

题目

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

我们使用整数 0、 12 分别表示红色、白色和蓝色。

必须在不使用库的sort函数的情况下解决这个问题。

示例

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

提示

  • n == nums.length
  • 1 <= n <= 300
  • nums[i] 为 01 或 2

进阶

  • 你可以不使用代码库中的排序函数来解决这道题吗?
  • 你能想出一个仅使用常数空间的一趟扫描算法吗?

代码实现

要将数组中的3中元素进行排序,我们可以定义3个指针,分别划分3个元素的区域,中间部位的指针用来进行遍历操作,头尾两个部分的指针则用于做边界的划分以及元素的交换。

当遍历到当前的元素为 0 时,则需将其移动到数组的头部,同时右移0的边界,反之依然,当遍历到当前的元素为2时,则需将其移动到数组的尾部,同时左移2的边界。

class Solution {
    public void sortColors(int[] nums) {
        // 边界处理
        int len = nums.length;
        if (len < 2) {
            return;
        }
        
        // 0,1,2三个区间指针
        int zero = 0, one = 0, two = len - 1;

        // 当 1 和 2 相遇,则表示已经遍历完所有元素,终止循环
        while (one <= two) {
            // 移动数字 1 的指针,如果当前位置元素为 0,则将其交换至前面数字 0 的区域
            if (nums[one] == 0) {
                swap(nums, one, zero);
                zero++;
                one++;
            } else if (nums[one] == 1) {
                // 当前元素为 1,则继续往后遍历比较
                one++;
            } else {
                // 当前元素为 2,则将其移动至数组尾部,并将数字 2 的区间缩小
                swap(nums, one, two);
                two--;
            }
        }
    }

    private void swap(int[] nums, int i, int j) {
        // 交换两个元素的位置
        nums[i] = nums[i] + nums[j] - (nums[j] = nums[i]);
    }
}