leetcode-75. 颜色分类

139 阅读2分钟
import java.util.Arrays;

/**
 * ref:https://leetcode-cn.com/problems/sort-colors/
 * 给定一个包含红色、白色和蓝色,一共n个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
 * 此题中,我们使用整数0、1和2分别表示红色、白色和蓝色。
 * 输入:nums = [2,0,2,1,1,0]; 输出:[0,0,1,1,2,2]
 **/
public class SortColors {

    /**
     * 思路:
     * 比较简单的方案是第一步统计出0,1,2分别出现的次数,第二步迭代重新填充数组元素的值。
     * 该题目进阶要求空间复杂度O(1),时间复杂度O(n)。此时就只能扫描一遍既要完成排序,通常会涉及双指针或三指针。
     * 准备三个指针,分别是紫色代表2,绿色代表0,红色代表遍历数组。
     * 整体思路是数组两头分别存放的是绿色的0和紫色2,中间放1。
     * 红色指针开始遍历,
     *   遇到1:跳过,红色指针++,
     *   遇到0:和绿色指针交换,绿色指针++,红色指针++。此时,交互过来的值已经是排过序的,肯定是0或者1,不需要在比较。
     *   遇到2:和紫色指针交换,紫色指针--。此时交互过来的值有可能是0,1,2中的任何一种,如果直接红色指针++的话,
     *   会出现直接就将2放在当前位置了,在继续比较肯定不对。另外如果交互过来的值是0的话,也是需要再次交互后,才能最终确认位置的。
     * 直到红色指针下标大于紫色代表执行完毕。等于也不行,可能会出现红色指针是0的case。需要移动绿色
     * @param nums
     */
    public static void sortColor(int[] nums){
        int read = 0;
        int green = 0;
        int purple = nums.length-1;
        while(read<=purple){
            if(nums[read]==1){
                read++;
            }else if(nums[read]==0){
                swap(nums,read++,green++);
            } else if(nums[read]==2){
                swap(nums,read,purple--);
            }
        }
    }

    private static void swap(int[] nums, int read, int green) {
        int temp = nums[read];
        nums[read] = nums[green];
        nums[green] = temp;
    }

    public static void main(String[] args) {
        // [0,0,1,1,2,2]
        int[] nums = new int[]{2,0,2,1,1,0};
        // [0,1,2]
        //int[] nums = new int[]{2,0,1};
        // [0]
        //int[] nums = new int[]{0};
        // [1]
        //int[] nums = new int[]{1};
        sortColor(nums);
        System.out.println(Arrays.toString(nums));
    }
}