데이터 스트림에서 누락 된 숫자 결정


14

집합 에서 쌍으로 다른 숫자 의 스트림을받습니다 .{ 1 , , n }n1{1,,n}

스트림을 한 번 읽고 비트 의 메모리 만 사용하는 알고리즘으로 누락 된 숫자를 어떻게 확인할 수 있습니까?O(log2n)

답변:


7

알다시피 , 때문에 부호화 될 수있다 비트 이것은 메모리와 하나의 경로에서 수행 할 수 있습니다 ( 찾으십시오 .이 숫자는 누락되었습니다). S=n(n+1)i=1ni=n(n+1)2 O(로그(n))O(로그n)ScurrentSumS=n(n+1)2O(log(n))O(logn)ScurrentSum

그러나이 문제는 일반적인 경우 (상수 ) 에서 해결할 수 있습니다 . 우리는 누락 된 숫자 가 있으며 모두 알아냅니다. 이 경우 합을 계산하는 대신 모든 대해 의 j'st 거듭 제곱의 합을 계산하십시오 ( 는 누락 된 숫자이고 는 입력 숫자 라고 가정 합니다).k y i x i 1 j k x i y ikkyixi1jkxiyi

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

, , ... 이므로 간단히 계산할 수 있습니다 .S 1 = S y i S 2 = i 2y 2 iS1,...SkS1=SyiS2=i2yi2

이제 누락 된 숫자 를 찾으려면 을 풀고 모든 를 찾으십시오 .x 나는(1)xi

다음을 계산할 수 있습니다.

P 2 = x ix j P k = x i ( 2 )P1=xi , , ..., .P2=xixjPk=xi (2)

이를 위해 기억이 , , ...P1=S1P2=S12S22

그러나 는 계수 이지만 고유하게 인수 분해 되므로 누락 된 숫자를 찾을 수 있습니다.PiP=(xx1)(xx2)(xxk)P

이것들은 내 생각이 아니다. 이것을 읽으십시오 .


1
나는 얻지 못했다 (2). 아마도 당신이 합계의 세부 사항을 추가 한 경우? 가 그리워 합니까 ? Pk
Raphael

@Raphael, 는 Newton의 정체성입니다. 참조 된 Wiki 페이지를 보면 계산 아이디어를 얻을 수 있다고 생각합니다. 각 는 이전 , 로 계산할 수 있습니다 . 간단한 공식을 기억하십시오 이면 모든 거듭 제곱에 유사한 접근 방식을 적용 할 수 있습니다. 또한 는 무언가의 시그마이지만, 에는 가 없습니다 . 가 하나뿐이기 때문입니다 . PiPiPSj2x1x2=(x1+x2)2(x12+x22)PiPkΣΠ

가능한 한 대답은 합리적인 수준으로 자체적으로 포함되어야합니다. 당신은 몇 가지 공식을 제공, 왜 그들을 완료하지?
Raphael

11

위의 의견에서 :

스트림을 처리하기 전에, 할당 가 연락하는 비트, X : = N I = 1 B N ( I ) ( b를 i가 N ( ) 의 이진 표현 이다 점별 배타적을 또는). 순진하게, 이것은 O ( n ) 시간 이 걸린다 .log2nx:=i=1nbin(i)bin(i)iO(n)

하나는 다수의 스트림마다 판독 처리시 , 컴퓨팅 X : = X B N ( J ) . k{ 1 , 의 단일 숫자라고 하자 . . . n } 스트림에 포함되지 않습니다. 전체 스트림을 읽은 후 x = ( n i = 1 b i n ( i ) )( i k bjx:=xbin(j)k{1,...n} 원하는 결과를 얻었다.

x=(i=1nbin(i))(ikbin(i))=bin(k)ik(bin(i)bin(i))=bin(k),

따라서, 우리가 사용 공간 및 전반적인 실행이 O ( N을 ) .O(logn)O(n)


3
이것을 진정한 스트리밍 단일 패스 알고리즘으로 만드는 쉬운 최적화를 제안 할 수 있습니다 : 시간 단계 , x 또는 x with b i n ( i ) 및 입력 b i n ( j ) 을 사용하여 스트림에 도착했습니다. 이것은 n을 미리 알지 못하는 경우에도 작동하도록 할 수있는 추가 이점이 있습니다 . x에 할당 된 단일 비트로 시작하고 필요에 따라 할당 된 공간을 "증가"하면됩니다. 나는엑스bin(i)bin(j)nx
Sasho Nikolov

0

HdM의 솔루션이 작동합니다. 테스트하기 위해 C ++로 코딩했습니다. 나는를 제한 할 수 없습니다 value 비트,하지만 난 당신이 쉽게 비트의 수는 실제로 설정되어 있는지 방법만을 보여줄 수 있어요.O(log2n)

의사 코드를 원하는 경우 독점 또는 ( ) 로 간단한 작업을 사용하십시오 .fold

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

손파 방지 : A 는 입력보다 더 많은 비트를 필요로하지 않으므로, 위의 중간 결과가 입력의 최대 비트 ( O ( log 2 n ) 비트 이상)를 요구하지 않습니다. 는 교환 적이며 x x = 0 이므로 위를 확장하고 스트림에 존재하는 모든 데이터를 쌍으로 묶으면 일치하지 않는 단일 값인 누락 된 숫자 만 남게됩니다.O(log2n)xx=0

#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
대신 알고리즘의 읽을 수있는 (의사) 코드를 대신 게시하십시오 (기본 건너 뛰기). 또한, 어느 정도의 정확성 증명 / 인수가 포함되어야합니다.
Raphael

4
@ edA-qamort-ora-y 귀하의 답변은 독자가 C ++을 알고 있다고 가정합니다. 이 언어에 익숙하지 않은 사람에게는 볼 내용이 없습니다. 관련 구절을 찾고 그 내용을 이해하는 것은 어려운 일입니다. 읽을 수있는 의사 코드는 이것이 더 나은 대답이 될 것입니다. C ++은 컴퓨터 과학 사이트에서 실제로 유용하지 않습니다.
Gilles 'SO- 악마 그만'

3
제 답변이 유용하지 않다면 사람들은 투표 할 필요가 없습니다.
edA-qa mort-ora-y

2
실제로 C ++ 코드를 작성하고 테스트하는 데 시간이 걸리는 +1 불행히도 다른 사람들이 지적했듯이 그렇지 않습니다. 아직도 당신은 이것에 노력을 넣어!
Julien Lebot

9
나는이 대답의 요점을 알 수 없다. 당신은 다른 사람의 해결책을 취한다. 그것은 매우 간단하고 명백히 매우 효율적이며 그것을 "테스트"한다. 왜 테스트가 필요한가요? 이것은 컴퓨터가 숫자를 올바르게 추가하는지 테스트하는 것과 같습니다. 그리고 코드에도 사소한 것이 없습니다.
Sasho Nikolov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.