计数排序

9.计数排序

计数排序是一个非基于比较的排序算法,它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。 [1] 当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(nlog(n)), 如归并排序,堆排序)

最坏、最好、平均时间复杂度:N+K ; 空间复杂度为:N+K

K不能省略,因为K为范围,受范围影响很大,当O(k)>O(n*log(n))时,受益低。

相关资料:https://blog.csdn.net/qq_42111463/article/details/84146915

   static int[] countSort(int[] a) {
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        for (int i = 0; i < a.length; i++) {
            max = a[i] > max ? a[i] : max;
            min = a[i] < min ? a[i] : min;
        }
        int[] help = new int[max - min + 1];
        for (int i = 0; i < a.length; i++) {
            help[a[i] - min]++;//最小的数放在下标为0的位置
        }      //////////////////////////////////////////////////////////
        //基本数据类型做法,直接输出到原数组排序;空间复杂度为K
//        int j = 0;
//        for (int i = 0; i < help.length; i++) {
//            while (help[i]-- > 0) {//当计数数组不为0时,
//                a[j++] = i + min;//将下标对应的数(i+min)依次填入原数组中
//            }
//        }
        //////////////////////////////////////////////////////////
        //对象如何保证稳定性  排名数组和新数组排序,空间复杂度:N+K
        //1.将统计数组变形为排名数组
        int sum = 0;//当前排名
        for (int i = 0; i < help.length; i++)//统计数组做变形,后面的元素等于前面元素的和,排名
        {
            sum += help[i];
            help[i] = sum;
        }
//////////////////计数数组变形为排名数组优化
//        for (int i = 1; i < help.length; i++)//统计数组做变形,后面的元素等于前面元素的排名加上自身的计数个数
//        {
//            help[i] += help[i-1];
//        }
//////////////////取数排序过程分析
        //此时将计数数组变成了排名数组,
        //再逆序输出原数组,将原数组的每一个数根据排名数组的下标去找排名,放在新数组中;
        //同时把排名数组对应位置的名次-1
        int[] sortArr = new int[a.length];
        for (int j = a.length - 1; j >= 0; j--) {
            sortArr[help[(a[j]-min)]-1]=a[j];//a[j]是原数组的数, a[j]-min是在排名数组中对应的下标,
            // help[a[j]-min]是对应的排名,help[a[j]-min]-1是在新建存放稳定数组中的存放位置
            help[(a[j]-min)]--;//同时将该下标的排名-1
        }
////////////////取数排序可以简化为一条语句
//        for(int i=a.length-1;i>=0;i--){
//            b[--c[a[i]-min]]=a[i];//按存取的方式取出c的元素
//        }
        return sortArr;//将排好序的稳定数组返回
    }
}
//优化版
  public static int[] countSort(int[]a){
    int b[] = new int[a.length];
    int max = a[0],min = a[0];
    for(int i:a){
       max = a[i] > max ? a[i] : max;
       min = a[i] < min ? a[i] : min;
      }
    }//这里k的大小是要排序的数组中,元素大小的极值差+1
    int c[]=new int[max-min+1];//初始化计数数组
    for(int i=0;i<a.length;++i){
      c[a[i]-min]+=1;//优化过的地方,减小了数组c的大小
    }
    for(int i=1;i<c.length;++i){//计数变排名数组
      c[i]=c[i]+c[i-1];
    }
    for(int i=a.length-1;i>=0;--i){//稳定取数
      b[--c[a[i]-min]]=a[i];//按存取的方式取出c的元素
    }
  return b;
  }
}
全部评论

相关推荐

老树开花:可以开始投了,不用等到觉得完全准备好。一边投一边根据面试反馈改简历是最高效的方式。简历上项目描述建议突出你解决的具体问题,比如编辑器的性能优化、大文档渲染怎么处理的,而不只是列技术栈。中厂前端实习现在竞争确实激烈,建议同时关注一些有AI业务的团队,前端加AI应用是很有差异化的组合。Vue全家桶基础扎实的话可以往SSR或者跨端方向延伸,这些是面试加分项。加油,时间还来得及。
点赞 评论 收藏
分享
个人背景:学院二本计科专业&nbsp;大二开始实习个人经历:安克创新&nbsp;、理想汽车、字节跳动碎碎念:我做事只有三分钟热度。看到进了大厂的同学,我会羡慕,也会跟着努力上进;但遇到好看的小说,我又会放下手头的事沉迷其中,之前的坚持也就中断了。我有些自卑,总觉得自己学历和外貌都不够好。之前偶然在网上受到关注,我就喜欢上了上网,因为这里有很多人认可我。但我也很在意别人的评价,偶尔看到嘲讽的言论,会触发我的自卑情绪,让我感到愤怒。有时候我会强硬地回怼,有时候又会懦弱地选择无视。我也有虚荣心。不管是拿到安克、理想还是字节的机会,我在分享的时候都会带着这份心思。我会特意强调自己学历不好,是为了衬托出过程的艰难,以此显得自己更厉害。我知道,人往往会炫耀自己缺少的东西,来掩盖内心的空洞。我总想着走捷径,不太喜欢踏踏实实地做事。找实习的时候,我花了更多时间在研究面试技巧上,而不是提升专业能力。我会反复听面试录音分析技巧,看面试教程学习怎么和不同的面试官沟通,还会每天自言自语练习语言表达,同学都觉得我有点奇怪。我的实习生涯里,侥幸和运气占了很大一部分。我总在想,如果有一天我失去了这份幸运,这些特质可能会让我一蹶不振。ps:&nbsp;很多人会问我学习路线和经验&nbsp;但是就像我上面说的&nbsp;我的实习过程靠的很多是关键节点的运气&nbsp;技术上面我可能不如很多人&nbsp;&nbsp;所以请大家理性求助和理性参考我的回答&nbsp;附上我的投递记录
我的offer在哪里...:从去年看到现在,飞升哥就是榜样
我的求职进度条
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务