Loading

Leetcode 0075. 颜色分类 难度:mid

Leetcode 0075. 颜色分类 难度:mid

题目

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

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

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

示例:

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

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

代码实现:

思路1:
三指针的方法,思路非常简单,就是左右两个分别指向等待填充的0,2位置;
中间一个指针遍历 数组中元素。
遇到0, 交换到左侧; (交换回来的数,只能是1,因此可以跳过)

如果不跳过:0位置是值:0原地交换,会死循环。
遇到2,交换到右侧;(交换回来可能是0,1,2)后续可能还需要继续交换;
遇到1,跳过;

时间复杂度为:O(n)

class Solution {
    public void sortColors(int[] nums) {
        int left = 0 , right = nums.length -1;
        int i = 0;

        while(i <= right){
            if(nums[i] == 0){
                swap(nums, i, left);
                left ++;
                // 左侧交换回来的只能是1
                i++;
            } else if(nums[i] == 2){
                swap(nums, i, right);
                //右侧交换回来的,可能是0,1,2
                right --;
            } else {
                i++;
            }
        }

    }

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

思路2: 值是有取值范围的,我们可以直接使用count_sort();
继续排序需要额外的k个值空间。
时间复杂度:O(n); //第一趟:统计n 个元素; 第二趟:计数K个元素;第三趟: 从后往前,放置元素;
计数排序

class Solution {
    public void sortColors(int[] nums) {
        int[] count = new int[3];
        for(int num :nums){
            count[num] ++;
        }
        for(int i = 1; i < 3; i++ ){
            count[i] += count[i-1];
        }
        int[] ans = new int[nums.length];
        for(int i = nums.length -1; i >= 0; i--){
            ans[count[nums[i]]-1] = nums[i];
            count[nums[i]]--;
        }
        System.arraycopy(ans, 0, nums,0, nums.length);

    }
}
posted @ 2020-10-07 10:26  Sidewinder  阅读(112)  评论(0编辑  收藏  举报