• 基本排序排序算法


    时空复杂度:

    冒泡排序:时间O(n^2),额外空间O(1)

    插入排序:时间O(n^2),额外空间O(1)

    选择排序:时间O(n^2),额外空间O(1)

    基数排序:时间O(k*n)(k=logN_max),额外空间O(n)(临时存储)+O(B)(记数,B为基的大小)

    记数排序:时间O(n+k),额外空间O(k)

    希尔排序:时间O(n*logn^2),额外空间O(1)

    快速排序:时间O(n*log(n)),额外空间O(logn)(递归栈)

    归并排序:时间O(n*log(n)),额外空间O(n)(临时数组)+O(logn)(递归栈)

    堆排序:  时间O(n*log(n)) 

    使快速排序退化的例子:

    n, n-1, n-2, n-3.......3,2,1,快速排序具有O(n^2)的复杂度。

    优化方法:随机选择划分元素,而不是固定选择最左面的元素。

    对归并来说,一个很不理想的例子:

    1,2,3,…… , n

    对有序序列还是需要O(nlogn)的时间复杂度。

    优化方法:找到序列的连续自增段,把这样的自增段进行合并。

    稳定排序和不稳定排序

    稳定的排序算法:冒泡排序、插入排序、基数排序、记数排序、归并排序

    非稳定排序算法:希尔排序、选择排序、快速排序、堆排序

    实际上稳定排序可以实现成非稳定的,看具体的实现过程。有些同学误以为自己写了一个冒泡排序就是稳定的,注意比较的时候是">=" 还是">"。

    内部排序与外部排序

    http://zh.wikipedia.org/zh/%E5%A4%96%E6%8E%92%E5%BA%8F

    内部排序:内部排序是指待排序列完全存放在内存中所进行的排序过程,适合不太大的元素序列。

    外部排序:外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。最常用的外部排序是多路归并排序。对于外部排序,影响速度的最主要因素为访问磁盘的次数,所以设计外部排序算法时,尽可能减少访问磁盘的次数。

    对于外部排序多路归并算法的时间复杂度进行简要分析。

    设有n个数,分成k段,之后利用m路归并 。

    t1 = n*log(n/k) 每段分别排序  n*log(n/k)。

    t2 = n*logk    每趟对n个数合并(每个数每趟只操作一次),一共logk趟,

    t3 = n * (T_read + T_write) * logk 从文件中读取和写入数字花费的时间,

    设每读取一个数的耗时为T_read,每次写一个数耗时为T_write,

    T(n) = t1 + t2+t3 = n*log(n/k) + n*logk + n*(T_read+T_write)*logk ,其中logk是以m为底的。

    所以,为了减少访问磁盘的次数,必须增大基m,但是m并不是越大越好,如果越大,则在m个数中选择最大值会越慢,所以一般都选m=9。

    逆序数问题

    对于序列 x1,x2,x3.......xn

    若存在i>j,且满足x[i] < x[j],则称(x[i],x[j])构成一个逆序对, 一个序列所有的逆序对的数目叫做这个序列的逆序数。

    例如序列 :5 4 3 2 1

    逆序数为 1+2+3+4 = 10

    利用归并排序可以快速的求得一个序列的逆序数。

    寻找第K大数算法

    问题1:给出一个序列,求这个序列第K大的数(离线)

    比较通用的算法:

    (1) 利用快速排序的划分。每次可以省去一部分的数进行查找。

    设下一次的查找百分比为q<1,

    时间 T(n) = n + T(n*q)

                         = n + n*q + T(n*q^2)

                         = n + n*q + n*q^2 + T(n*q^3)

                         ......

                         = n(1 + q + q^2 + q^3 + ......)

                         = n(1*(1-q^k)/(1-q))

    当q=1/2时, T(n) = 2n = O(n)。

    这种方法最坏情况下的时间复杂度是O(n^2)。

    那么有没有能够保证最坏时间复杂度是O(n)的算法吗?有

    (2) 最坏时间下是O(n)复杂度的算法

    http://en.wikipedia.org/wiki/Selection_algorithm 或参见<<算法导论>> P190-P191

    针对普通的划分和随机化划分的缺点,对选择划分数进行改进:选择中位数的中位数进行划分。

    假设函数Find(A, k, n)返回的是A数组中第k大的元素,新的查找算法如下:

    1:将输入数组的n个元素划分为n/5组,每组5个元素,至多有一个组的元素数目小于5。

    2:寻找n/5个组的每个组的中位数。对每个组的5个元素利用插入排序,之后选择中位数。

    3: 对第2步找到的n/5个中位数递归调用Find函数,找出其中位数x。

    4:利用中位数x对输入数组进行划分。并得出x的排位。

    5:如果第四步得到的x的排位为k,则返回x。如果x的排位大于k,则在低区进行递归查找,否则在高区进行查找。

    因为x是中位数,除去x本身所在的组和那个元素数目小于5的组不算,大于x的元素数目至少为3*(1/2)*(n/5 - 2) = 3*n/10 - 6。

    同理小于x的元素数目至少为3*n/10 - 6。那么第4步最多有n-(3*n/10-6) = 7*n/10+6个元素参加下次的递归查找。

    设Find(A, k, n)花费时间为T(n)。

    则T(n) = t1 + t2 + t3 + t4 + t5。

    t1 = O(n)    (分成n/5组)

    t2 = O(n)    (每组进行选择可以看做O(1)时间花费)

    t3 = T(n/5)   (对n/5个中位数递归选择)

    t4 = O(n)     (根据x进行划分)

    t5 = T(7*n/10 + 6)  (下一次递归选择)

    T(n) = T(n/5) + T(7*n/10 + 6) + O(n)

    最后可推算出T(n)=O(n),但是个人认为常数比较大。

    K非常小时情况下的选择第K大元素算法:

    利用冒泡或者选择排序,时间复杂度O(K*n)。

     

     

  • 相关阅读:
    Beyond Compare 30天评估期已过解决方案
    windows快捷键及命令
    表情包的转码解码
    html+css实现文本从右向左
    js控制页面滚回上一记录位置
    将base64转为二进制
    牛客挑战赛58
    字符串专题
    牛客挑战赛59
    组合数学专题
  • 原文地址:https://www.cnblogs.com/haolujun/p/2699612.html
Copyright © 2020-2023  润新知