LeetCode75. 颜色分类

一、题目描述

二、解法

思路1:计数排序。分别统计0,1,2的元素个数。

复杂度分析:时间复杂度:O(n);空间复杂度:O(k), k为元素的取值范围; 需要扫描数组两遍。

思路2:三路快排。 只需要遍历数组一遍

重点是设计循环不变量,定义zero和two的含义后,在循环中始终要维护这个定义。

class Solution {
    public void sortColors(int[] nums) {
        if (nums == null || nums.length == 0) return;
        /**
         *  方法1:计数排序法。分别统计0,1,2出现的次数
         *        扫描数组两趟
         *        时间复杂度:O(n) 空间复杂度:O(k),k为元素的取值范围
         */
        /*
        int[] count = new int[3];
        for (int num : nums) {
            count[num]++;
        }
        int index = 0;
        for (int i = 0; i < count.length; i++) {
            for (int j = 0; j < count[i]; j++) {
                nums[index++] = i;
            }
        }
        */
        /**
         * 方法2: 三路快排。只需要遍历一趟数组
         *       由于待排序的数组中有很多与标定点v相等的值,
         *       因此把数据分为三份,<v =v >v,之后对小于v和大于v递归进行三路快排
         *  arr[0..zero] == 0   arr[zero+1...i-1]==1  arr[two...n-1] == 2
         */
        int zero = -1;           // arr[0..zero] == 0
        int two = nums.length;  // arr[two...n-1] == 2
        for (int i = 0; i < two;) {
            if (nums[i] == 1) {
                i++;
            }else if (nums[i] == 2) {
//                nums[i] = nums[--two]; // 用赋值 代替 交换数据
//                nums[two] = 2;
                swap(nums,i,--two);
            }else { // nums[i] == 0
//                nums[i++] = 1;   // nums[i]和nums[zero]的赋值顺序如果颠倒会出错。。
//                nums[++zero] = 0;
                swap(nums,i++,++zero);
            }
        }
    }
    private void swap(int[] nums, int a, int b) {
        int temp = nums[a];
        nums[a] = nums[b];
        nums[b] = temp;
    }
}

重要参考(循环不变量的设计):

快速排序 partition(重点在设计循环不变量)

 

原文地址:https://www.cnblogs.com/HuangYJ/p/14091374.html