Odpowiedzi:
Wiesz , a ponieważ można zakodować wbitachO(log(n)),można to zrobić wpamięciO(logn)i na jednej ścieżce (po prostu znajdźS-cur to brakuje liczba).
Ale problem ten można rozwiązać w ogólnym przypadku (dla stałej ): mamy k brakujących liczb, znajdź je wszystkie. W tym przypadku zamiast obliczania tylko suma rw I , suma oblicz z j'st potęgi x i dla wszystkich 1 ≤ j ≤ k (Przypuszczałem X i jest brakujące numery i y i to numery wejściowe):
Pamiętaj, że możesz obliczyć po prostu dlatego, S 1 = S - Ď y I , Ś 2 = Σ i 2 - Σ Y 2 i ...
Teraz, aby znaleźć brakujące liczby, powinieneś rozwiązać aby znaleźć wszystkie x i .
Możesz obliczyć:
, P 2 = ∑ x i ⋅ x j , ..., P k = ∏ x i .
W tym celu należy pamiętać, że , P 2 = S 2 1 - S 2 , ...
Ale to współczynniki P = ( x - x 1 ) ⋅ ( x - x 2 ) ⋯ ( x - x k ), ale P można by rozłożyć na czynniki specjalne, dzięki czemu można znaleźć brakujące liczby.
To nie są moje myśli; przeczytaj to .
Z powyższego komentarza:
Before processing the stream, allocate bits, in which you write ( is the binary representation of and is pointwise exclusive-or). Naively, this takes time.
Upon processing the stream, whenever one reads a number , compute . Let be the single number from that is not included in the stream. After having read the whole stream, we have
Hence, we used space, and have an overall runtime of .
HdM's solution works. I coded it in C++ to test it. I can't limit the value
to bits, but I'm sure you can easily show how only that number of bits is actually set.
For those that want pseudo code, using a simple operation with exclusive or ():
Hand-wavey proof: A never requires more bits than its input, so it follows that no intermediate result in the above requires more than the maximum bits of the input (so bits). is commutative, and , thus if you expand the above and pair off all data present in the stream you'll be left only with a single un-matched value, the missing number.
#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;
}