1

题目要求

Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.

Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.

Note:
You are not suppose to use the library's sort function for this problem.
    
Follow up:
A rather straight forward solution is a two-pass algorithm using counting sort.
First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.

Could you come up with an one-pass algorithm using only constant space?

假设一个数组中存在3个数字0,1,2。将数组中的数字排序,尽量实现O(n)时间复杂度。

思路一:O(2n)

就如题中所言,先遍历一遍数组,分别记录0,1,2出现的次数。然后在第二次遍历数组的过程中,将相应次数的0,1,2依序填入数组中。代码如下:

public void sortColors1(int[] nums) {
        int numOfZero = 0;
        int numOfOne = 0;
        for(int i = 0 ; i < nums.length ; i++){
            if(nums[i]==0){
                numOfZero++;
            }else if(nums[i]==1){
                numOfOne++;
            }
        }
        for(int i = 0 ; i<nums.length ; i++){
            if(numOfZero>0){
                nums[i] = 0;
                numOfZero--;
            }else if(numOfOne>0){
                nums[i] = 1;
                numOfOne--;
            }else{
                nums[i] = 2;
            }
        }
    }

思路二:双指针

如何能在一次遍历的过程中实现三个数字的排序呢~这就需要使用到双指针。我们要确保左指针之前的数值全部是0,右指针之后的数值全部是2。这样他就可以确保左右指针之间的数字为1,从而实现0,1,2的排序。代码如下:

    private void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
    
    //保证i前全是0,j后全是2,然后通过交换使得i和j中间确定为1,O(n)
    public void sortColors2(int[] nums) {
        int i = 0;
        int j = nums.length - 1;
        int ptr = 0;
        while (ptr <= j) {
            if (nums[ptr] == 0) {
                swap(nums, i++, ptr++);
            } else if (nums[ptr] == 1) {
                ptr++;
            } else {
                swap(nums, ptr, j--);
            }
        }
    }

clipboard.png
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~


raledong
2.7k 声望2k 粉丝

心怀远方,负重前行