夯实算法-颜色分类

93 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的28天,点击查看活动详情

题目:LeetCode

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

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 必须在不使用库内置的 sort 函数的情况下解决这个问题。

示例 1:

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

示例 2:

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

提示:

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

解题思路

解法一:

分析该题由提示可知,这题元素只有0,1或者2, 就可以使用计数排序。 先遍历一遍,统计0, 1, 2的个数,然后先把0填充到结果数组,再填充1, 最后填充2, 就得到结果数组。

解法二: 使用双指针left,right,指针left左侧都是0,指针right右侧都是2,初始化left,right在数组的两端。

我们使用一个遍历变量i,遍历数组时nums[i]为0,则与左指针指向数字交换位置,然后左指针和i都向后移动,i左侧直到左指针都是1,当nums[i]为2时,则与右指针指向数字交换位置,然后右指针向左移动,i不变因为还要判断交换来的数字是什么,如果nums[i]为1,则不交换i向后移动,循环终止条件时i超过了右指针,此时后面已经是2,无需继续交换

代码实现

解法一:

public void sortColors(int[] nums) {
    int[] countMap = {
        0, 0, 0
    };
    Arrays.stream(nums).forEach(n -> countMap[n] ++);

    int index = 0;
    for (int k = 0; k < countMap.length; k++) {
        for (int i = index; i < index + countMap[k]; i++) {
            nums[i] = k;
        }
        index += countMap[k];
    }
}

解法二:

public void sortColors(int[] nums) {
    int left = 0, right = nums.length - 1;
    int i = 0;
    while (i <= right) {
        if (nums[i] == 0) {
            swap(nums, left, i);
            left++;
            i++;
        } else if (nums[i] == 2) {
            swap(nums, right, i);
            right--;
        } else {
            i++;
        }
    }
}

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

运行结果

解法一:

解法一.png

解法二:

解法二.png

复杂度分析

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

掘金(JUEJIN)  一起分享知识, Keep Learning!