Answers:
您知道,因为可以用位,这可以在内存和一条路径中完成(只需找到,这是缺少的数字)。小号=Ñ(Ñ+1) Ó(日志(Ñ))ø(日志Ñ)š-çÙ- [R[RËÑ吨小号ù米
但是这个问题可以在一般情况下(对于常数)解决:我们有缺失的数字,找出它们全部。在这种情况下,不是仅计算总和,而是为所有计算的j'st幂的总和(我假设缺少数字,是输入数字):ķ ÿ 我X 我 1 ≤ Ĵ ≤ ķ X 我ÿ 我
请记住,您可以简单地计算,因为,,...S 1 = S - ∑ y i S 2 = ∑ i 2 - ∑ y 2 i
现在要查找缺失的数字,您应该解决来找到所有。x 我
您可以计算:
P 2 = Σ X 我 ⋅ X Ĵ P ķ = Π X 我(2 ),,...,。
为此,请记住 ,,...P 2 = S 2 1 − S 2
但是是系数,但是可以唯一地分解,因此您可以找到缺失的数字。 P = (x − x 1)⋅ (x − x 2)⋯ (x − x k)P
这些不是我的想法;阅读这个。
从上面的评论:
处理流之前,分配位,在其中写X := ⨁ Ñ 我= 1 b 我Ñ(我)(b 我Ñ(我)是的二进制表示我和⊕是逐点exclusive-要么)。天真的,这需要O(n )时间。
一旦处理流,每当一个读取数,计算X := X ⊕ b 我Ñ(Ĵ )。让ķ是从单数{ 1 ,。。。Ñ }不包含所述信息流中。在阅读整个流之后,我们有 X = (Ñ ⨁我= 1 b 我Ñ(我)) ⊕ (⨁ 我≠ ķ b 得到所需的结果。
因此,我们使用了空间,并且总体运行时间为O(n )。
HdM的解决方案有效。我用C ++进行了编码以对其进行测试。我不能将其限制value
为位,但是我敢肯定,您可以轻松地显示出实际上只设置了多少位。
对于那些想伪代码,使用一个简单的操作与异或(⊕):
手波浪卷发证明:甲从未需要比其输入更多的位,所以它遵循上面没有中间结果在需要超过该输入的最大比特(所以Ô (登录2 Ñ )位)。⊕是可交换的,并且X ⊕ X = 0,因此如果展开上述和一对关闭所有本你将只剩下一个未匹配的值,缺少的数量流中的数据。
#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>
using namespace std;
void find_missing( int const * stream, int len );
int main( int argc, char ** argv )
{
if( argc < 2 )
{
cerr << "Syntax: " << argv[0] << " N" << endl;
return 1;
}
int n = atoi( argv[1] );
//construct sequence
vector<int> seq;
for( int i=1; i <= n; ++i )
seq.push_back( i );
//remove a number and remember it
srand( unsigned(time(0)) );
int remove = (rand() % n) + 1;
seq.erase( seq.begin() + (remove - 1) );
cout << "Removed: " << remove << endl;
//give the stream a random order
std::random_shuffle( seq.begin(), seq.end() );
find_missing( &seq[0], int(seq.size()) );
}
//HdM's solution
void find_missing( int const * stream, int len )
{
//create initial value of n sequence xor'ed (n == len+1)
int value = 0;
for( int i=0; i < (len+1); ++i )
value = value ^ (i+1);
//xor all items in stream
for( int i=0; i < len; ++i, ++stream )
value = value ^ *stream;
//what's left is the missing number
cout << "Found: " << value << endl;
}