算法分析

133 阅读1分钟

线性时间选择

问题描述

  在某个序列中找到第k小的数

算法分析

  基于快速排序思想,取出序列中一个元素m,将序列划分为两个子序列A、B,A序列中的元素均小于等于m,B中元素均大于m,当k大于A的长度时,选择B作为子问题序列,k=k-A.length,否则A作为子问题序列。确定子问题序列后。判断子序列长度若为1,则找到目标值,否则重复最开始的划分操作。

  该算法的关键在于取哪个元素作为m,如果随机取的话,最坏情况下的时间复杂度为O(n2)O(n^2),需要选择一个取值方法(线性时间O(n)),使得每个子问题的规模都会缩小父问题的一定倍数,比如父问题的规模是n,子问题的规模为0.75n。如果取出的m值可以满足此要求就可以得到以下递归方程:T(n)kT(n/b)+O(n)T(n)≤kT(n/b)+O(n),此时T(n)=O(n)T(n)=O(n)


问题案例

  • 在长度为n的序列s中,找到最接近中位数的k个数,要求T(n)=O(n)T(n)=O(n)
    思路
    1. 使用线性时间选择找到s中的中位数m-----------------O(n)
    2. 求出所有元素与m的差值,D[i]=s[i]mD[i]=|s[i]-m|------O(n)
    3. 利用线性时间选择找到在D中第k-1小的数设为j-------O(n)
    4. 输出s[i],其中i满足:D[i]≤D[j]---------------------------O(n)