Jawaban:
Anda tahu , dan karenaS=n(n+1) dapat dikodekan dalambitO(log(n))ini dapat dilakukan dalammemoriO(logn)dan dalam satu jalur (cukup cariS-currentSum, ini adalah nomor yang hilang).
Tetapi masalah ini dapat diselesaikan dalam kasus umum (untuk konstan ): kami memiliki nomor k yang hilang, cari tahu semuanya. Dalam hal ini, alih-alih menghitung hanya jumlah y i , hitung jumlah kekuatan pertama x i untuk semua 1 ≤ j ≤ k (saya berasumsi x i adalah angka yang hilang dan y i adalah angka input):
Ingat bahwa Anda dapat menghitung sederhana, karena S 1 = S - Σ y i , S 2 = Σ i 2 - Σ y 2 , ...
Sekarang untuk menemukan nomor yang hilang, Anda harus memecahkan untuk menemukan semua .
Anda dapat menghitung:
, P 2 = ∑ x i ⋅ x j , ..., P k = ∏ x i ( 2 ) .
Untuk ini ingat bahwa , P 2 = S 2 1 - S 2 , ...
Tetapi adalah koefisien dari P tetapi dapat diperhitungkan secara unik, sehingga Anda dapat menemukan angka yang hilang.
Ini bukan pikiran saya; Baca ini .
Dari komentar di atas:
Sebelum memproses aliran, alokasikan bit, di mana Anda menulis x : = ⨁ n i = 1 b i n ( i ) ( b i n ( i adalah representasi biner dari i dan ⊕ adalah pointwise eksklusif- atau). Secara naif, ini membutuhkan waktu O ( n ) .
Setelah memproses streaming, setiap kali seseorang membaca angka , hitung x : = x ⊕ b i n ( j ) . Biarkan k menjadi nomor tunggal dari { 1 , . . . n } yang tidak termasuk dalam aliran. Setelah membaca seluruh aliran, kita memiliki x = ( n ⨁ i = 1 b i n ( i ) ) ⊕ ( ⨁ i ≠ k b
Solusi HdM bekerja. Saya mengkodekannya dalam C ++ untuk mengujinya. Saya tidak bisa membatasi value
untuk bit, tapi saya yakin Anda dapat dengan mudah menunjukkan bagaimana hanya jumlah bit yang benar-benar ditetapkan.
Bagi yang menginginkan kode pseudo, gunakan yang sederhana operasi dengan eksklusif atau ():
Bukti bergelombang: A tidak pernah memerlukan lebih banyak bit dari inputnya, jadi itu berarti bahwa tidak ada hasil antara di atas membutuhkan lebih dari bit maksimum input (jadi bit). bersifat komutatif, dan , jadi jika Anda memperluas yang di atas dan memasangkan semua data yang ada dalam aliran Anda akan dibiarkan hanya dengan satu nilai yang tidak cocok, angka yang hilang.
#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;
}