zoukankan      html  css  js  c++  java
  • lintcode148

    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.
    Example
    Given [1, 0, 1, 2], sort it in-place to [0, 1, 1, 2].
    Challenge
    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?
    Notice
    You are not suppose to use the library's sort function for this problem.
    You should do it in-place (sort numbers in the original array).

    答题顺序:counting sort -> 扫描两次 -> 三根指针

    三根指针。两根从两边夹逼,中间那根比左指针略快,从左开始扫描。所以这是不对称的,循环内处理从而不对称。
    左指针L是下一个放0的位置(它的左边全都是0了,现在指着的不知道),右指针R是下一个放2的位置(它的右边全都是2了),中指针i是扫描用的。
    在中指针还没碰到右指针时循环。
    1.扫到0和左指针换,左指针增,中指针增。
    2.扫到1,中指针增。
    3.扫到2和右指针换,右指针减。(注意中指针不能动)

    细节:
    1.为什么扫到2时中指针不能动呢:因为不对称,刚换好的时候中指针这时指着一个右边过来的未知数,因为右边没处理过012都有可能,你要是中指针前移了就漏了处理这个未来过来的未知数了。
    2.为什么扫到0时中指针可以动呢?因为中指针比左指针快,从而中指针已经把左指针的位置扫描过了,左指针那个数只可能是01,不可能是2否则早就被换到后面了。0的话位置准了不用管,1的话本来也就是要后移动也不用管。
    3.为什么扫到0时中指针必须动呢?如果不动,那只有中指针扫到1的时候才会向前挪动,那碰到02的话就原地踏步死循环了。让01动2不动还是可行的,因为2那里还是处理了一下要做交换,那换到01就可以继续动了,换到2还有接着换的机会也没关系。

    实现

    public class Solution {
        /**
         * @param nums: A list of integer which is 0, 1 or 2 
         * @return: nothing
         */
        public void sortColors(int[] nums) {
            // write your code here
            int zeroes = 0;
            int twos = nums.length - 1;
            int ones = 0;
            while (ones <= twos) {
                if (nums[ones] == 0) {
                    swap(nums, zeroes, ones);
                    zeroes++;
                    ones++;
                } else if (nums[ones] == 1) {
                    ones++;
                } else {
                    swap(nums, twos, ones);
                    twos--;
                }
            }
        }
        
        private void swap(int[] nums, int i, int j) {
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
    }

    九章

    public class Solution {
        public void sortColors(int[] a) {
            if (a == null || a.length <= 1) {
                return;
            }
            
            int pl = 0;
            int pr = a.length - 1;
            int i = 0;
            while (i <= pr) {
                if (a[i] == 0) {
                    swap(a, pl, i);
                    pl++;
                    i++;
                } else if(a[i] == 1) {
                    i++;
                } else {
                    swap(a, pr, i);
                    pr--;
                }
            }
        }
        
        private void swap(int[] a, int i, int j) {
            int tmp = a[i];
            a[i] = a[j];
            a[j] = tmp;
        }
    }
  • 相关阅读:
    Codeforces Round #687 A. Prison Break
    最小生成树自用笔记(Kruskal算法+prim算法)
    Codeforces Round #686 (Div. 3)(A->D)(模拟,vector,数学)
    Acwing 852. spfa判断负环
    Linux内核分析_课程学习总结报告
    结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程
    深入理解系统调用
    基于mykernel 2.0编写一个操作系统内核
    何评测一个软件工程师的计算机网络知识水平与网络编程技能水平?——参考试题
    TCP三次握手Linux源码解析
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/9479426.html
Copyright © 2011-2022 走看看