颜色分类
给定一个包含红,白,蓝且长度为n的数组,将数组元素进行分类使相同颜色的元素相邻,并按照红、白、蓝的顺序进行排序。
我们可以使用整数0,1和2分别代表红,白,蓝。
样例
注意
不能使用代码库中的排序函数来解决这个问题
说明
一个相当直接的解决方案是使用计数排序扫描2遍的算法。
首先,迭代数组计算0,1,2出现的次数,然后依次用0,1,2出现的次数去覆盖数组。
你否能想出一个仅使用常数级额外空间复杂度且只扫描遍历一遍数组的算法?
代码写的乱糟糟的,难得写了注释。
想法就是把0交换至左边,2交换至右边。
1 class Solution { 2 //总耗时: 14896 ms 3 4 /** 5 * @param nums: A list of integer which is 0, 1 or 2 6 * @return: nothing 7 */ 8 public void sortColors(int[] nums) { 9 int low = 0; 10 int high = nums.length-1; 11 //先找到最左的非0和最右的非2 12 while(nums[low] == 0 && low < high) low++; 13 while(nums[high] == 2 && low < high) high--; 14 15 while(nums[low] == 2 || nums[high] == 0 && low < high) { 16 //如果最左非0是2或者最右非2是0,则将其换至右边或左边 17 if(nums[low] == 2) { 18 if(nums[high] == 0) { 19 nums[low++] = 0; 20 nums[high--] = 2; 21 }else { 22 nums[high--] = 2; 23 nums[low] = 1; 24 } 25 }else { 26 if(nums[high] == 0) { 27 nums[low++] = 0; 28 nums[high] = 1; 29 } 30 } 31 //找到最左的非0和最右的非2 32 while(nums[low] == 0 && low < high) low++; 33 while(nums[high] == 2 && low < high) high--; 34 } 35 36 for(int i=low+1;i<high && low < high;i++) { 37 //此时最左非0和最右非2都是1,用i找到0或2,交换到左端或右端 38 if(nums[i] == 0) { 39 nums[low++] = 0; 40 nums[i] = 1; 41 }else { 42 if(nums[i] == 2) { 43 nums[high--] = 2; 44 nums[i] = 1; 45 } 46 } 47 48 //找到最左的非0和最右的非2 49 while(nums[low] == 0 && low < high) low++; 50 while(nums[high] == 2 && low < high) high--; 51 52 while(nums[low] == 2 || nums[high] == 0 && low < high) { 53 //如果最左非0是2或者最右非2是0,则将其换至右边或左边 54 if(nums[low] == 2) { 55 if(nums[high] == 0) { 56 nums[low++] = 0; 57 nums[high--] = 2; 58 }else { 59 nums[high--] = 2; 60 nums[low] = 1; 61 } 62 }else { 63 if(nums[high] == 0) { 64 nums[low++] = 0; 65 nums[high] = 1; 66 } 67 } 68 //找到最左的非0和最右的非2 69 while(nums[low] == 0 && low < high) low++; 70 while(nums[high] == 2 && low < high) high--; 71 } 72 //若此时的low>=i,显然要重新设置i 73 if(i <= low) i = low+1; 74 } 75 //当上面的循环结束时,分类就已完成,只遍历了一次nums,辅助空间为常数 76 } 77 }
时间: 2024-10-06 18:43:12