• 查找之找出N个整数中最大的K个数


    题目一:找出N个整数中第K大的数

    类似下边的类快排算法,递归实现,应该可以,需要验证一下。平均复杂度O(n).



    题目二:找出N个整数中最大的K个数

    两个比较好的解法:O(nlogk)

    1快排和递归

    【解法二】

    回忆一下快速排序,快排中的每一步,都是将待排数据分做两组,其中一组
    的数据的任何一个数都比另一组中的任何一个大,然后再对两组分别做类似的操
    作,然后继续下去……

    在本问题中,假设 N 个数存储在数组 S 中,我们从数组 S 中随机找出一个
    元素 X,把数组分为两部分 Sa 和 Sb。Sa 中的元素大于等于 X,Sb 中元素小于 X。

    这时,有两种可能性:

    1. Sa中元素的个数小于K,Sa中所有的数和Sb中最大的K-|Sa|个元素(|Sa|指Sa

    中元素的个数)就是数组S中最大的K个数。

    2. Sa中元素的个数大于或等于K,则需要返回Sa中最大的K个元素。

    这样递归下去,不断把问题分解成更小的问题,平均时间复杂度 O(N *
    log2K)。伪代码如下:

    Kbig(S, k):
    if(k <= 0):
    return [ ] // 返回空数组

    if(length S <= k):
    return S
    (Sa, Sb) = Partition(S)
    return Kbig(Sa, k).Append(Kbig(Sb, k – length Sa)

    Partition(S):

    Sa = [] // 初始化为空数组

    Sb = []
    // 随机选择一个数作为分组标准,以避免特殊数据下的算法退化
    // 也可以通过对整个数据进行洗牌预处理实现这个目的
    // Swap(S[1], S[Random() % length S])
    p = S[1]
    for i in [2: length S]:
    S[i] > p ? Sa.Append(S[i]) : Sb.Append(S[i])
    // 将p加入较小的组, 可以避免分组失败, 也使分组更均匀,提高效率
    length Sa < length Sb ? Sa.Append(p) : Sb.Append(p)
    return (Sa, Sb)

    2 堆排序

    不妨设 N > K,前 K 个数中的最大 K 个数是一个退化的情况,所有 K 个数
    就是最大的 K 个数。如果考虑第 K+1 个数 X 呢?如果 X 比最大的 K 个数中的最
    小的数 Y 小,那么最大的 K 个数还是保持不变。如果 X 比 Y 大,那么最大的 K
    个数应该去掉 Y,而包含 X。如果用一个数组来存储最大的 K 个数,每新加入一
    个数 X,就扫描一遍数组,得到数组中最小的数 Y。用 X 替代 Y,或者保持原数
    组不变。这样的方法,所耗费的时间为 O(N * K)。

    进一步,可以用容量为 K 的最小堆来存储最大的 K 个数。最小堆的堆顶元
    素就是最大 K 个数中最小的一个。每次新考虑一个数 X,如果 X 比堆顶的元素
    Y 小,则不需要改变原来的堆,因为这个元素比最大的 K 个数小。如果 X 比堆
    顶元素大,那么用 X 替换堆顶的元素 Y。在 X 替换堆顶元素 Y 之后,X 可能破
    坏最小堆的结构(每个结点都比它的父亲结点大),需要更新堆来维持堆的性
    质。更新过程花费的时间复杂度为 O(log2K)。



     编程之美

    图 2-1 是一个堆,用一个数组 h[]表示。每个元素 h[i],它的父亲结点是 h[i/2],
    儿子结点是 h[2 * i + 1]和 h[2 * i + 2]。每新考虑一个数 X,需要进行的更新操作伪
    代码如下:

    if(X > h[0])
    {
    h[0] = X;
    p = 0;
    while(p < K)
    {
    q = 2 * p + 1;
    if(q >= K)
    break;
    if((q < K-1) && (h[q + 1] < h[q]))
    q = q + 1;
    if(h[q] < h[p])
    {
    t = h[p];
    h[p] = h[q];
    h[q] = t;
    p = q;
    }
    else
    break;
    }
    }

    原帖:http://blog.csdn.net/scottgly/article/details/6958227
  • 相关阅读:
    集训队日常训练20180518-DIV1
    集训队日常训练20180513-DIV1
    python类的使用与多文件组织
    性能指标
    python调用.so
    动态链接库的使用
    python读写xml文件
    使用python读取文本中结构化数据
    python画图
    numpy及scipy的使用
  • 原文地址:https://www.cnblogs.com/catkins/p/5270739.html
Copyright © 2020-2023  润新知