一、题目描述
二、解法
思路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; } }
重要参考(循环不变量的设计):