Câu trả lời:
Bạn biết và vìS=n(n+1) có thể được mã hóa bằngcác bitO(log(n)),điều này có thể được thực hiện trongbộ nhớO(logn)và trong một đường dẫn (chỉ cần tìmS-currentSum, đây là số bị thiếu).
Nhưng vấn đề này có thể được giải quyết trong trường hợp chung (đối với hằng số ): chúng ta có k số bị thiếu, tìm ra tất cả chúng. Trong trường hợp này thay vì chỉ tính tổng của y i , hãy tính tổng công suất j'st của x i cho tất cả 1 ≤ j ≤ k (Tôi giả sử x i bị thiếu số và y i là số đầu vào):
Hãy nhớ rằng bạn có thể tính đơn giản, vì S 1 = S - ∑ y i , S 2 = ∑ i 2 - ∑ y 2 i , ...
Bây giờ để tìm số còn thiếu, bạn nên giải để tìm tất cả x i .
Bạn có thể tính toán:
, P 2 = ∑ x i ⋅ x j , ..., P k = ∏ x i ( 2 ) .
Đối với điều này hãy nhớ rằng , P 2 = S 2 1 - S 2 , ...
Nhưng là hệ số của nhưng P có thể là yếu tốduy nhất, vì vậy bạn có thể tìm số còn thiếu.
Đây không phải là suy nghĩ của tôi; đọc này .
Từ nhận xét trên:
Trước khi xử lý dòng, phân bổ bit, trong đó bạn viết x : = ⨁ n i = 1 b i n ( i ) ( b i n ( i ) là biểu diễn nhị phân của tôi và ⊕ là pointwise exclusive- hoặc là). Ngây thơ, điều này mất thời gian O ( n ) .
Khi xử lý luồng, bất cứ khi nào người ta đọc một số , hãy tính x : = x ⊕ b i n ( j ) . Gọi k là số duy nhất từ { 1 , . . . n } không được bao gồm trong luồng. Sau khi đọc toàn bộ dòng, chúng ta có x = ( n ⨁ i = 1 b i i n ( i ) ) = b i n ( k mang lại kết quả mong muốn.
Do đó, chúng tôi đã sử dụng không gian và có thời gian chạy tổng thể là O ( n ) .
value
#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;
}