查找数组中丢失的元素
将0到n这n+1个数中取n个放到一个大小为n的数组里,找到丢弃的那个数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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之间
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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(?)的算法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//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的数目不是很大的情况下可以使用如下方法.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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的额外空间