เราได้รับกระแสของตัวเลขที่แตกต่างจากจำนวนจากชุด }
ฉันจะกำหนดจำนวนที่ขาดหายไปด้วยอัลกอริทึมที่อ่านกระแสข้อมูลหนึ่งครั้งและใช้หน่วยความจำของบิตเท่านั้น( ล็อก2 n ) ได้อย่างไร
เราได้รับกระแสของตัวเลขที่แตกต่างจากจำนวนจากชุด }
ฉันจะกำหนดจำนวนที่ขาดหายไปด้วยอัลกอริทึมที่อ่านกระแสข้อมูลหนึ่งครั้งและใช้หน่วยความจำของบิตเท่านั้น( ล็อก2 n ) ได้อย่างไร
คำตอบ:
คุณรู้จักและเพราะS=n(n+1)สามารถเขียนโค้ดในO(log(n))บิตนี้สามารถทำได้ในหน่วยความจำO(logn)และในเส้นทางเดียว (เพียงหาS-currentsumนี้จะหายไปจำนวน)
แต่ปัญหานี้สามารถแก้ไขได้ในกรณีทั่วไป (สำหรับค่าคงที่ ): เรามีตัวเลขที่หายไปkให้หาพวกเขาทั้งหมด ในกรณีนี้แทนที่จะคำนวณเพียงผลรวมของy i , คำนวณผลรวมของ j'st power ของx iสำหรับทั้งหมด1 ≤ j ≤ k (ฉันสันนิษฐานว่าx iขาดตัวเลขและy iคือตัวเลขอินพุต):
โปรดจำไว้ว่าคุณสามารถคำนวณเพียงเพราะว่าS 1 = S - ∑ y i , S 2 = ∑ i 2 - ∑ y 2 i , ...
ตอนนี้สำหรับการหาตัวเลขที่หายไปคุณควรจะแก้เพื่อค้นหาทุกxฉัน
คุณสามารถคำนวณ:
, P 2 = ∑ x i ⋅ , ... , P k = ∏ x i ( 2 ) )
สำหรับสิ่งนี้โปรดจำไว้ว่า , P 2 = S 2 1 - S 2 , ...
แต่คือสัมประสิทธิ์ของP = ( x - x 1 ) ⋅ ( x - x 2 ) ⋯ ( x - x k )แต่Pสามารถแยกตัวประกอบได้อย่างไม่ซ้ำใครดังนั้นคุณสามารถหาตัวเลขที่หายไปได้
จากความคิดเห็นด้านบน:
ก่อนประมวลผลสตรีมจัดสรรบิตซึ่งคุณเขียนx : = ⨁ n ฉัน= 1ขฉันn ( i ) ( b ฉันn ( i )คือการแทนเลขฐานสองของiและ⊕เป็นค่าเฉพาะจุด - หรือ). อย่างไร้เดียงสานี่ใช้O ( n )เวลา
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;
}