时间复杂度 O(n) 级排序算法

《算法导论》定理 8.1:在最坏情况下,任何比较排序算法都需要做 O(nlogn) 次比较。

《算法导论》推论 8.2:堆排序和归并排序都是渐进最优的比较排序算法。

所以时间复杂度 O(n) 级排序算法都是不进行比较的算法而通过元素本身的特性进行排序的算法,因此都有一定的限制,并不是在所有情况都能使用,主要的有:计数排序,基数排序和桶排序。

计数排序

计数排序需要提前知道所有元素的取值范围,比如【0,10】,依据这个范围建立一个数组t[11],并将其全部初始化为0,接下来遍历需要排序的数组,假设遍历到的数字为i,则t[i]++。遍历结束后数组t中每个位置的数字就代表对应元素出现的次数,接下来遍历数组t,并把对应个数的元素放入原数组中。

以上步骤是建立在需要排序的元素是单纯的数字的情况下,如果是一个比较复杂的元素,那么可能需要利用队列或者每次都计算好该元素放入的位置。

数组的相对排序

时间复杂度 O(n) 级排序算法_第1张图片

时间复杂度 O(n) 级排序算法_第2张图片 

 这道题中元素的范围是比较小的,所以适合使用计数排序。

public class Solution {
    public int[] RelativeSortArray(int[] arr1, int[] arr2) {
        int[] res=new int[arr1.Length];
        int[] num1=new int[1001];
        for(int i=0;i<1001;i++)
        num1[i]=0;
        for(int i=0;i

基数排序

想一下我们是怎么对日期进行排序的。比如对这样三个日期进行排序:2014 年 11月 7 日,2020 年 1 月 9 日,2020 年 7 月 10 日。

我们大脑中对日期排序的思维过程是:先看年份,2014 比 2020 要小,所以 2014 年这个日期应该放在其他两个日期前面。另外两个日期年份相等,所以我们比较一下月份,1 比 7 要小,所以 1 月这个日期应该放在 7 月这个日期前面。

对一组整数排序也是这样,依次比较各个位上的数字,最后就得到了有序序列。

基数排序分两种,一种是比较符合我们直觉的从高位到低位的比较,另一种则是反过来。实际上算法中常用的是后一种,因为前一种,在每次比较后都要根据结果分为排序完成(该位上仅有这一个数)的和未完成的(该位有多个数)。比如上面的例子中比较完年份后就要把2014 年 1 月 7 日排除,否则根据月份排序它就落到后面了。

如果从低位到高位比较非负整数,步骤是这样的:计算出最大的整数的位数max,建立10个队列,从个位开始,遍历按照该位上的数字把元素放入对应的队列中,遍历结束后按0~9依次出队所有元素,并放回数组中,进行下一位的比较,循环直到最高位。

最大间距

时间复杂度 O(n) 级排序算法_第3张图片

 时间复杂度 O(n) 级排序算法_第4张图片

 元素的取值范围是比较大的,所以不适合用计数排序。

注意队列数组中的每个都要初始化。

public class Solution {
    public int MaximumGap(int[] nums) {
        if(nums.Length<2)
        return 0;
        Queue[] q = new Queue[10];
        Queue q0 = new Queue();q[0] = q0;
        Queue q1 = new Queue();q[1] = q1;
        Queue q2 = new Queue();q[2] = q2;
        Queue q3 = new Queue();q[3] = q3;
        Queue q4 = new Queue();q[4] = q4;
        Queue q5 = new Queue();q[5] = q5;
        Queue q6 = new Queue();q[6] = q6;
        Queue q7 = new Queue();q[7] = q7;
        Queue q8 = new Queue();q[8] = q8;
        Queue q9 = new Queue();q[9] = q9;
        int maxlv=0;
        for(int i=0;imaxlv)
            maxlv=(int)Math.Log10((double)nums[i]);

        sort(nums,q,maxlv);
        int max=0;
        for(int i=1;imax)
            max=nums[i]-nums[i-1];

        return max;
    }
    public void sort(int[] nums,Queue[] q,int maxlv)
    {
        for(int i=0;i<=maxlv;i++)
        {
            for(int j=0;j

桶排序

桶排序的思想是:

  • 将区间划分为 n 个相同大小的子区间,每个子区间称为一个桶
  • 遍历数组,将每个数字装入桶中
  • 对每个桶内的数字单独排序,这里需要采用其他排序算法,如插入、归并、快排等
  • 最后按照顺序将所有桶内的数字合并起来

桶排序有诸多问题,比如如何划分区间,用什么数据结构储存桶,所以不常使用

你可能感兴趣的:(数据结构,数据结构,算法,leetcode,c#,排序算法)