डेटा स्ट्रीम में गुम संख्या निर्धारित करें


14

हमें सेट- से युग्मय विभिन्न संख्याओं की एक धारा प्राप्त होती है ।n1{1,,n}

मैं एक एल्गोरिथ्म के साथ लापता संख्या कैसे निर्धारित कर सकता हूं जो एक बार स्ट्रीम पढ़ता है और केवल बिट्स की मेमोरी का उपयोग करता है ?O(log2n)

जवाबों:


7

तुम्हें पता है i=1ni=n(n+1)2 , और क्योंकिS=n(n+1)2 कोO(log(n))बिट्समें कोडितकिया जा सकता है यहO(logn)मेमोरी में और एक पथ मेंकिया जा सकता है(बसScurrentSum, यह अनुपलब्ध संख्या है)।

लेकिन इस समस्या को सामान्य स्थिति में हल किया जा सकता है (निरंतर ): हमारे पास k लापता संख्याएं हैं, उन सभी का पता लगाएं। बजाय सिर्फ का योग की गणना के इस मामले में y मैं , की j'st सत्ता के calculate राशि एक्स मैं सभी के लिए 1 जे कश्मीर (मैं मान लिया एक्स मैं नंबर याद आ रही है और y मैं इनपुट संख्या है):kkyixi1jkxiyi

i=1kxi=S1,i=1kxi2=S2,i=1kxik=Sk (1)

याद रखें कि आप गणना कर सकते हैं बस, क्योंकि एस 1 = एस - Σ y मैं , एस 2 = Σ मैं 2 - Σ y 2 मैं , ...S1,...SkS1=SyiS2=i2yi2

अब लापता संख्याओं को खोजने के लिए आपको सभी x i को खोजने के लिए हल करना चाहिए ।(1)xi

आप गणना कर सकते हैं:

, पी 2 = Σ एक्स मैंएक्स जे , ..., पी कश्मीर = Π x मैं ( 2 )P1=xiP2=xixjPk=xi (2)

इसके लिए याद रखें कि , पी 2 = एस 2 1 - एस 2P1=S1 , ...P2=S12S22

लेकिन के गुणांकों है पी = ( एक्स - एक्स 1 ) ( एक्स - एक्स 2 ) ( एक्स - एक्स कश्मीर ) लेकिन पी कारक हो सकता है , विशिष्ट इसलिए गुम संख्या पा सकते हैं।PiP=(xx1)(xx2)(xxk)P

ये मेरे विचार नहीं हैं; पढ़ा यह


1
मुझे नहीं मिलता (2)। हो सकता है कि यदि आप रकम के विवरण में जोड़ लें? क्या एक ∑ को याद करता है ? Pk
राफेल

@ राफेल, न्यूटन की पहचान है, मुझे लगता है कि यदि आप मेरे संदर्भित विकी पृष्ठ पर एक नज़र डालते हैं तो आप गणना का विचार प्राप्त कर सकते हैं, प्रत्येक पी I की गणना पिछले पी एस, एस जे द्वारा की जा सकती है , सरल सूत्र याद रखें: 2 x 1एक्स 2 = ( एक्स 1 + x 2 ) 2 - ( एक्स 2 1 + x 2 2 ) , आप सभी शक्तियों के समान दृष्टिकोण लागू कर सकते हैं। जैसा कि मैंने P i लिखा हैPiPiPSj2x1x2=(x1+x2)2(x12+x22)Pi is sigma of something, but Pk doesn't have any Σ, because there is just one Π.

Be that as it may, answers should be self-contained to a reasonable degree. You give some formulae, so why not make them complete?
Raphael

11

From the comment above:

Before processing the stream, allocate log2n bits, in which you write x:=i=1nbin(i) (bin(i) is the binary representation of i and is pointwise exclusive-or). Naively, this takes O(n) time.

Upon processing the stream, whenever one reads a number j, compute x:=xbin(j). Let k be the single number from {1,...n} that is not included in the stream. After having read the whole stream, we have

x=(i=1nbin(i))(ikbin(i))=bin(k)ik(bin(i)bin(i))=bin(k),
yielding the desired result.

Hence, we used O(logn) space, and have an overall runtime of O(n).


3
may I suggest an easy optimization that makes this a true streaming single-pass algorithm: at time step i, xor x with bin(i) and with the input bin(j) that has arrived on the stream. this has the added benefit that you can make it work even if n is not known ahead of time: just start with a single bit allocated for x and "grow" the allocated space as necessary.
Sasho Nikolov

0

HdM's solution works. I coded it in C++ to test it. I can't limit the value to O(log2n) 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 fold operation with exclusive or ():

Missing=fold(,{1,,N}InputStream)

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 O(log2n) bits). is commutative, and xx=0, 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;
}

3
Please post readable (pseudo) code of only the algorithm instead (skip main). Also, a correctness proof/argument at some level should be included.
Raphael

4
@ edA-qamort-ora-y आपका उत्तर मानता है कि पाठक C ++ जानता है। किसी ऐसे व्यक्ति के लिए जो इस भाषा से परिचित नहीं है, देखने के लिए कुछ भी नहीं है: प्रासंगिक मार्ग खोजने और समझने के लिए कि यह क्या कर रहा है, दोनों एक चुनौती है। पठनीय छद्मकोश यह एक बेहतर उत्तर देगा। कंप्यूटर साइंस साइट पर C ++ वास्तव में उपयोगी नहीं है।
Gilles 'SO- stop being evil'

3
यदि मेरा जवाब उपयोगी साबित नहीं होता है तो लोगों को इसके लिए वोट करने की आवश्यकता नहीं है।
edA-qa mort-ora-y

2
+1 वास्तव में C ++ कोड लिखने और इसका परीक्षण करने के लिए समय ले रहा है। दुर्भाग्य से अन्य लोगों ने बताया कि यह एसओ नहीं है। फिर भी आपने इसमें प्रयास किया है!
जूलियन लेबोट

9
I don't get the point of this answer: you take someone else's solution, which is very simple and obviously very efficient, and "test" it. Why is testing necessary? This is like testing your computer adds numbers correctly. And there is nothing nontrivial abt your code either.
Sasho Nikolov
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.