• 查找数组中丢失的元素


    将0到n这n+1个数中取n个放到一个大小为n的数组里,找到丢弃的那个数

    代码
    int search(int *x, int n)
    {
    int sum = ((1 + n) * n) >> 1;
    for (int i = 0; i < n; ++i)
    {
    sum
    -= x[i];
    }
    return sum;
    }

    //if array is sorted
    int binSearch(int *x, int n)
    {
    int s = 0;
    int e = n;
    int u = 0;
    while (s < e)
    {
    u
    = (s + e) / 2;
    if (x[u] != u)
    {
    e
    = u;
    }
    else
    {
    s
    = u + 1;
    }
    }
    return s;
    }

    前一个算法复杂度是O(n),不过有可能sum过大,会溢出,后一个算法复杂度是O(lbn)

    下面是一个不会溢出的版本,相当于把求和的部分拆散了,这个计算过程中sum的值会保持在0-n之间

    代码
    int search1(int *x, int n)
    {
    int tmp = 1;
    int sum = 0;
    for (int i = 0; i < n; ++i)
    {
    while (sum < x[i])
    {
    sum
    += tmp++;
    }
    sum
    -= x[i];
    }
    if (tmp == n)
    return tmp;
    return sum;
    }

    如果缺失的是k个且k<<n,可以通过解多项式的方法来解出缺失的k个数,如果已排序,可以使用如下复杂度为klbn(?)的算法

    代码
    //x: 存储n+k个连续整数中的n个
    //miss: 返回缺失的k个
    //s: x的起始位置
    //e: x的结束位置
    //sn: n+k个连续整数的第一个
    //en: n+k个连续整数的最后一个
    //missIndex: miss数组的索引
    void binSearch1(int* x, int *miss, int s, int e, int sn, int en, int &missIndex)
    {
    if ((e - s) == (en - sn))
    return;
    if ((e - s) < 2)
    {
    for (; sn < en; ++sn)
    {
    if (x[s] != sn)
    {
    miss[missIndex
    ++] = sn;
    }
    else if (s < e)
    {
    ++s;
    }
    }
    }
    else
    {
    int u = (s + e) / 2;
    binSearch1(x, miss, s, u, sn, x[u], missIndex);
    binSearch1(x, miss, u, e, x[u], en, missIndex);
    }
    }

    如果k比较多,而n的数目不是很大的情况下可以使用如下方法.

    代码
    void search2(int *x, int *miss)
    {
    bitset
    <N + K> bs;
    for (int i = 0; i < N; ++i)
    {
    bs.
    set(x[i]);
    }
    for (int i = 0, j = 0; i < N + K; ++i)
    {
    if (!bs[i])
    {
    miss[j
    ++] = i;
    }
    }
    }

    //if array is sorted
    void search3(int *x, int *miss, int n, int k)
    {
    int u = 0;
    int j = 0;
    for (int i = 0; i < n; ++u)
    {
    if (x[i] != u)
    miss[j
    ++] = u;
    else
    ++i;
    }
    for (;u < n + k; ++u)
    {
    miss[j
    ++] = u;
    }
    }

    两个的算法复杂度都是O(n+k),不过前者要多扫一次数组,还要一个bitset的额外空间

  • 相关阅读:
    象限极角排序
    并查集与二部图
    POJ 1743 后缀数组不重叠最长重复子串
    POJ 2104 【主席树】【区间第K大】
    两串前缀最长后缀
    Codeforces 450D Jzzhu and Cities [heap优化dij]
    Codeforces 119C DP
    HDU 3068 [最长回文子串]
    Codeforces 132E Bits of merry old England 【最小费用最大流】
    ZOJ 3911Prime Query [素数处理 + 线段树]
  • 原文地址:https://www.cnblogs.com/triStoneL/p/1941905.html
Copyright © 2020-2023  润新知