题目大意:将颜色排序,将同颜色的放置在相邻的位置,0表示red,1表示white,2表示blue,即最后的排序颜色应该是0,1,2。(最好能实现遍历一遍,常数空间)
法一:直接用库函数排序。o(nlgn)。代码如下(耗时1ms):
1 public void sortColors(int[] nums) { 2 Arrays.sort(nums); 3 }
法二:遍历两遍,常数空间。第一遍分别计数有多少个0,1,2,然后根据计数再将0,1,2填入原来的数组中。o(n)。代码如下(耗时1ms):
1 public void sortColors(int[] nums) { 2 int cnt0 = 0, cnt1 = 0, cnt2 = 0; 3 //第一遍遍历计数 4 for(int i = 0; i < nums.length; i++) { 5 if(nums[i] == 0) { 6 cnt0++; 7 } 8 else if(nums[i] == 1) { 9 cnt1++; 10 } 11 else { 12 cnt2++; 13 } 14 } 15 //第二遍遍历重写数组 16 int k = 0; 17 for(int i = 0; i < cnt0; i++) { 18 nums[k++] = 0; 19 } 20 for(int i = 0; i < cnt1; i++) { 21 nums[k++] = 1; 22 } 23 for(int i = 0; i < cnt2; i++) { 24 nums[k++] = 2; 25 } 26 }
法三:遍历一遍,常数空间。两个指针,red指向左边开头,blue指向右边结尾,从头开始遍历数组,如果遇到red,则交换到前面,如果遇到blue,则交换到后面。如果遇到white则保持不变。代码如下(耗时1ms):
1 public void sortColors(int[] nums) { 2 int red = 0, blue = nums.length - 1; 3 for(int i = 0; i <= blue; i++) { 4 //如果当前是red,则将当前元素交换到前面,red位置后移一位 5 if(nums[i] == 0) { 6 int tmp = nums[i]; 7 //这里不需要回退遍历,因为将0换到前面,肯定不会导致2还排在0的前面遍历不到的情况。 8 nums[i] = nums[red]; 9 nums[red++] = tmp; 10 } 11 //如果当前是blue,则将当前元素交换到后面,blue位置前移一位 12 else if(nums[i] == 2) { 13 int tmp = nums[i]; 14 //这里i--是必须的,因为有可能出现1,2,0的情况,将0换到2的前面,而如果不再遍历0的话,就会导致错误,所以换2之后,需要回退遍历一下 15 nums[i--] = nums[blue]; 16 nums[blue--] = tmp; 17 } 18 } 19 }
法四:遍历一遍,常数空间。巧妙的计数的结合,具体代码如下(耗时1ms):
1 public void sortColors(int[] nums) { 2 int cnt0 = -1, cnt1 = -1, cnt2 = -1; 3 for(int i = 0; i < nums.length; i++) { 4 if(nums[i] == 0) { 5 nums[++cnt2] = 2; 6 nums[++cnt1] = 1; 7 nums[++cnt0] = 0; 8 } 9 else if(nums[i] == 1) { 10 nums[++cnt2] = 2; 11 nums[++cnt1] = 1; 12 } 13 else { 14 nums[++cnt2] = 2; 15 } 16 } 17 }