IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    数组排序算法--Counting Sort

    longhao (longtask@gmail.com)发表于 2010-10-09 22:31:36
    love 0

        江湖中又现阿里的算法面试题目:找出数组中重复次数最多的元素并打印。我碰巧在《编程珠玑》中看到了,javaeye上的帖子的各种实现效率或多或少的有性能问题,更是有人好高骛远的讨论到mapreduce了,明显的把裝B的难度从“芙蓉姐姐”直接转到“小月月”。

        涉及到重复元素的问题,在线性时间排序算法(Linear-Time Sorting)中到计数排序(Counting Sorting)或许是解决这个问题的。简单介绍下计数排序:

    1. 输入数组A[n],需要确认元素是1...k之间的数值,如果不知道K的值,则需要遍历求出最大值。
    2. 建立数组B[k],初始化的数值为0
    3. 遍历数组A[n],如果A[i]=j,则B[j] + 1
    4. 遍历数组B[k],根据B[j]的值决定j打印多少次。

       计数排序算法的时间复杂度是O(k) + O(n) + O(k) + O(n) = O(k + n),在数组中的元素重复较少的时候,和快速排序比起来效率较低。 这个题目只是求出B[j]的最大值,最后一步遍历B[k]都可以省去,在遍历A[n]的时候可以直接记录就可以了。

        具体算法的java实现如下:

    package com.longtask.algorithms;

    import java.util.Arrays;
    import java.util.Random;

    public class CountingSort {
        private static final int N= 10000;
        private static final int K= 1000;
        /**
         * 得到计数数组
         * @param num
         * @return
         */
        public static int[] computeCountingNum(int[] num){
            int maxAppearNum = 0;
            int count = 0;
            int[] countingNum = new int[K];
            int value,countTmpValue;
            for(int i=0;i<N;i++){
                value = num[i];
                countTmpValue = countingNum[value];
                //查找出现次数最多的数字
                if(countTmpValue > count){
                    count = countTmpValue;
                    maxAppearNum = value;
                }                
                countingNum[value] = countingNum[value] + 1;
            }
            //打印出满足阿里面试要求到数据
            System.out.println("\n"+maxAppearNum);
            System.out.println(count);
            return countingNum;
        }
        /**
         * 遍历计数数组,得到排序结果
         * @param num
         * @return
         */
        public static int[] sortedNum(int[] num){
            int[] countingNum = computeCountingNum(num);
            int[] sortedNum = new int[N];
            int value;
            int j = 0;
            for(int i=0;i<K;i++){
                value = countingNum[i];
                if(value > 0){
                    while(value > 0){
                        sortedNum[j] = i;
                        --value;
                        ++j;
                    }
                }
            }
            return sortedNum;
        }
        /**
         * 产生随机数
         * @return
         */
        public static int[] randomNumber(){
            int[] num = new int[N];
            Random random = new Random();
            for(int i=0;i<N;i++){
                int m = random.nextInt(K);
                num[i] = m;
            }
            return num;
        }
       
        public static void main(String[] args) {
            int[] num = CountingSort.randomNumber();
            //计数排序耗时
            long t1 = System.currentTimeMillis();
            CountingSort.sortedNum(num);
            long t2 = System.currentTimeMillis();
            System.out.print(t2-t1);
            System.out.println();
            //快速排序耗时
            long t3 = System.currentTimeMillis();
            Arrays.sort(num);
            long t4 = System.currentTimeMillis();
            System.out.print(t4-t3);
        }
    }

        最后测试了下快速排序和技术排序在重复数值较多的情况下的效率,明显技术排序更加靠谱。不同的场景选择不同的算法。

        线性时间排序算法(Linear-Time Sorting)合计有3种算法,如果你对文字感兴趣点击这里

        当然,一边喝点酒,一边听课是不是更爽,看这段视频吧!



沪ICP备19023445号-2号
友情链接