Finding two missing numbers

Tags:

간단한 퀴즈입니다.

You are given n consequent numbers not necessarily ranging from 1 to n, e.g., 3, 4, 5, …, and (3+n-1). From those n numbers, two numbers each of which is neither the smallest nor the biggest were removed. And the remaining n-2 numbers were shuffled and stored in an array.

Now, you want to find those two missing numbers. For example, given 11, 3, 5, 4, 8, 7, and 9, you want to find that 6 and 10 are missing. But you have the storage which is less than O(n) and you have O(n) time. How do you do that?

update:
One interesting answer is to use a quadratic equation. Suppose the Sv and Lv denote the smallest and the largest value in the array, respectively. Then, you can compute Sv + (Sv + 1) + … + Lv and Sv * (Sv + 1) * … * Lv. And then, you scan the array and compute the sum and the product of values. Now, suppose that those two missing numbers are A and B. From two sums and two products, you get A+B and A*B. So, this problem boils down to solving a quadratic equation.

However, this approach takes the space larger than O(n), because 1 * 2 * … * n = n! = O(n^n) and storing O(n^n) value needs O(nlogn) space.

푸신분은 답글을.. 질문도 답글로요.

Comments

16 responses to “Finding two missing numbers”

  1. JM Avatar

    (spoiler warnings)

    밑에 나오는 Related entries 가 정확한데요? ^^
    제 답) Minvalue, Maxvalue 를 찾고 mean 으로 (= 전체 구간의 median) 파티셔닝 (퀵소트의 그것처럼). 양쪽 파티션 중 갯수가 모자라는 쪽으로 재귀호출해서 들어가는 것을 반복합니다. 파티션 해봤는데 양쪽 다 하나씩 개수가 모자라다면 양쪽으로 재귀호출해야겠지만, 갈라질 일은 한번밖에 없으니 최대 linear time selection algorithm 두 번 실행하는 것과 같은 시간 복잡도겠죠. :)

    좀더 쉽게.. 하나가 비어 있다고 가정하고, 파티션 후에 개수가 모자라는 방향으로 재귀호출해서 들어가서 없는 원소를 찾는 selection 알고리즘을 작성합니다. 그리고, 양쪽 다 개수가 모자랄 때에 왼쪽으로 들어갈 것인지 오른쪽으로 들어갈지를 parameter 를 추가하도록 하죠. 그러면 select(0, n-1, LEFT), select(0, n-1, RIGHT) 두 번 호출로 해결. :-)

    문제 특성상 selection algorithm 에서 pivot 구하는데 고생할 일도 없을 것 같고 (매번 해당 구간의 median 을 쓰면 되니까요) 무난하게 O(N) 에 풀리는거 같습니다. ^^

  2. Anonymous Avatar
    Anonymous

    “…For example, given 11, 3, 5, 4, 7, and 9, you want to find that 6 and 10 are missing…”

    Then where is 8 ? :)

  3. abraxsus Avatar
    abraxsus

    걍 생각나는 답안..
    걍 array에 때려넣고 비어있는거 찾으면 되는거 아닌가??
    11,3,5,4,7,9,8 이 주어졌을때,
    a[11-11]=a[0] 에 11을 넣고
    a[11-3]=a[8] 에 3넣고
    a[11-5]=a[6] 에 5넣고…
    .
    .
    그렇게 한번 array에 넣어주고 다시 한번 훑으면서 남은 2개 찾으면 되겠네…
    그럼 time O(2n)=O(n)과 space O(n)에 되는거 아닌가..
    에..이러면 사실 2개만 빠졌든 몇개가 빠졌든 빠진 숫자들은 다 찾을수 있겠는뎅…
    내가 뭐 놓친거 있나??

    p.s. update부분과 JM님의 답안은 일단 못읽었음.. 귀차니즘의 한계에 도전한다…크흑…

  4. abraxsus Avatar
    abraxsus

    오.. quadratic equation쓰는 해법 훌륭하다고 봄.. 근데 takes the space larger than O(n), because 1 * 2 * … * n = n! = O(n^n) and storing O(n^n) value needs O(nlogn) space 라는것은, arbitrary precision을 생각하는것인가??..
    그리고 JM님의 답안도 멋지네요 :-)

  5. mkseo Avatar
    mkseo

    @anon: 죄송;;;; 업데이트할께요
    @jm: 정답!!! ㅋㅋㅋ 사실 이 문제 정답은 모르는데 제가 생각한 답이랑 같네요^^ 그나저나 역시 jm님 똑똑해요 ㅎㅎ
    @abraxsus: n^n은 매우 큰 숫자이고, 물론 precision을 보존 해야지. 그래야 A*B를 정확히 구하니까.

  6. MKSeo Avatar
    MKSeo

    @abraxsus: space O(n) 보다 적게 써야돼. 그러니까 space complexity 가 sublinear여야한다는 말.

  7. abraxsus Avatar
    abraxsus

    음.. less than O(n)은 이해하기 어려운걸.. O(logn)같은것을 얘기한다고하기엔 문제의 의도가 그것같지는 않고, jm님의 답안도 space는 O(n)인걸. 내가 아는한 sublinear라는것은 O(logn)이나 O(1)같은걸 얘기하는건데…
    아마도 문제에서는 array의 정확한 size를 n보다 작다고 제한하고 싶은 모양이지만,-_-;;
    사실 상수개의 변수를 더쓴것같은건 너도 알다시피 complexity에선 의미없지..
    space가 O(n)이라고 할때 굳이 partitioning을 통해서 그렇게 풀 이유는 납득하기 어려운걸..
    max/min구하는데 이미 1번의 스캐닝,
    recursive partitioning해서 2개의 답을 찾는데에 다시 최소 2번의 scanning이 드니까..

  8. mkseo Avatar
    mkseo

    아. 물론 데이터 자체의 저장소는 빼야함. 시간 복잡도 계산시 입력을 읽을 때 드는 시간을 제외하는 것처럼.

    문제의 원본은 모르지만 물론 O(n)보다 작다라고 하면 O(logn) 의 답을 내야한다고 생각해. jm님의 방법은 divide and conquer이므로 O(logn)만큼 리커젼이 일어나고 따라서 저장소 요구량도 O(logn)이라고 봐야되고.

  9. 이원구 Avatar

    제 생각도 abraxsus님과 비슷한데요. 일단 n개를 파티셔닝하는데 storage가 n개 필요하지 않나요?
    데이터 자체의 저장소를 빼야 한다는 말은 in-place로 파티셔닝을 하면 storage가 전혀 필요없다는 의미인 것 같은데 그런 경우가 가능하다면 다음과 같이 단순한 방법도 답이 될 것 같습니다.

    이 경우엔 (11, 3, 5, 4, 8, 7, 9의 경우)
    1. 먼저 첫번째 스캔에서 min, max 찾고 (min=3, max=11)
    2. 원래 저장소 외에 두개의 장소를 더 할당해서 두번째 스캔에서 값들을 제자리로 옮기고
    11, 3, 5, 4, 8, 7, 9, x, x
    3, 4, 5, x, 7, 8, 9, x, 11
    3. 세번째 스캔에서 빈 값을 찾으면 될 것 같네요. 성능은 3n, 즉 O(n)이 되고 storage는 2, 즉 O(1)이 됩니다.

    storage를 n/k로 하는 것은 답은 많이 있을 것 같은데 big-O를 쓴것으로 보아 이런 건 아닐것 같고요.

    그래서 저는 O(1) storage를 사용하는 quadratic equation 방법이 딱 맘에 드는데 알고리즘 문제에서 arbitrary precision까지 고려하라는 것은 좀… oTL

    그리고 “시간 복잡도 계산시 입력을 읽을 때 드는 시간을 제외하는 것처럼” 은 좀 이상한 것 같습니다. find 같은 알고리즘에서 O(n)은 입력을 읽는 시간이 아닌가요?

  10. abraxsus Avatar
    abraxsus

    그게.. 좀.. 그렇죠-_-;; 제 생각엔 일단,
    space든지 time이던지 complexity를 얘기할때 input/output까지도 다 포함하는것으로 알고있고요..
    예를 들어 n size의 array의 입력에 대해서 n size의 array를 출력하는 알고리즘이 있다고 할때
    출력에만 O(n)이 들어가기에 time은 최소 O(n)이 되죠..

    이원구님것도 제꺼랑 거의 같은데, 사실 min/max찾을 필요는 없기때문에 2번의 스캔이면 되죠..
    n-2사이즈의 array가 주어졌을때 2개만 덧붙여서 n사이즈의 array로 보고
    swap과 modular연산만 이용해주면 in-place로 소팅을 할수 있죠..
    (엄밀히 소팅은 아니지만, modular연산을 써서 걍 링을 만들어버리는거죠..
    소팅까지도 필요없으니까.. 그담에 스캔하면서 빈거 출력하면 되니까.)
    제 생각에는 이러면 time/space 모두 O(n)이 되죠..
    JM님의 답안 역시 time/space 모두 O(n)이죠..
    차이점이라면 제껀 space에서 2개의 변수를 더 써서 time complexity를 2n으로 했다면
    JM님의 답안에서는 time complexity가 3n이 되는 반면에 space가 in-place가 된다는거죠..

    문제를 좀더 확장해서 2개가 아니라 m개라고 하면,
    제껀 space O(n), time O(n)이 되고
    JM님꺼는 space O(n-m), time O(nm)정도 되겠네요..

    n,m의 크기에 따라 각기 장단점이 있을거라 봅니다..
    (물론 n,m의 크기에 따라 JM님의 알고리즘은 optimize의 여지가 크겠네요..
    n,m모두가 큰 sparce한 경우엔 걍 소팅해버리죠 머-_-;;)

    몇가지 생각을 더해보자면,
    저역시 quadratic equation을 쓴 방식이 깔끔하니 딱 마음에 드는데,
    곱의 값이 커지기때문에 arbitrary precision을 안쓴다면 데이터의 값의 범위가 무척 제한된다는점과
    그게 아니라고해도 곱과 합을 알때 두개의 해를 구하는것은 제곱근을 구해야하기때문에
    오히려 배꼽이 더 커질수 있다는 점, 설령 두개의 해가 양의 정수라는 점을 이용해서 잘 푼다고해도
    O(1)안에 구할수 있을지 회의적일뿐더러, 그렇게되면 data의 종류에 제한이 가해진다는 제약점,
    더 나아가 data가 floating number일때의 연산의 부정확성은 다룰수 없다는 한계점등..-_-;;
    수학적으로 깔끔한 해법이 공학에서 어떻게 무너질수 있나를 보여주는 예라고 생각됩니다-_-;;
    또, 2개가 아니라 3개,4개라면? -_-;; 3차/4차 방정식을 풀어야…쿨럭….

    또 하나는, 문제가 recursive해법을 써야한다고 꼬시는듯한-_-;;
    냄새를 풍긴다는.. 생각입니다.. 정석류의 정형화된 답안을 기다리는
    정형화된 문제라고나 할까요-_-;; 저라면 숱한 약점에도 불구하고 저 quadratic equation해법을
    내놓은 사람에게 점수를 주겠읍니다.

  11. mkseo Avatar
    mkseo

    글쿤요.. 이거 comb sort해버리면 땡이었네;;;; 그렇군그렇군.

    @abraxsus:
    요즘들어서의 생각인데, 이렇게 알고리즘을 묻는 문제를 수학적으로
    답해서는 안된다고 본다. 내가 사실 전에 Dynamic Programming에 대한
    답을 그냥 수식 하나로 적었더니 (요즘 과외하느라 온갖 공식에 빠삭했기때문에
    가능했음) 퀴즈 출제자가 별로 만족해하지 않던데 ㅎㅎ

    그러니까… 요는 퍼즐의 정답을 대답할때는 룰을 따라야한다는거지 ㅎㅎ
    물론 나도 quadratic equation 해답에 감탄했음은 사실.

  12. JM Avatar

    제가 늦게 와서 리플다는데.. 뭐 이런저런 경우에 다르겠지만 일반적으론 입출력 시간을 포함하지 않는 것이 맞다고 생각해요. (사실 이런거는 그냥 이론적인 논의일 뿐이지만.. ^^;) 일단 메모리에 한번 로딩한 후 데이터를 여러번 처리하는 경우가 많을 뿐더러 (대부분의 탐색 문제에선 특히나 그렇죠, 바이너리 서치 같은) 데이터를 로딩하지 않고 파일에서 그대로 처리하는 경우 같은것도 있을 수 있을 테니까요. 문제 해결에 ‘추가적으로 요구되는’ 시간이나 공간을 재는 것이 아닐까요? 이것은 어디까지나 개개인의 생각이 다른 것이겠지만, 예를 들어 레드블랙 트리에서의 탐색 시간을 디스크에 덤프된 트리를 읽어오는 시간까지 해서 O(n) 이라고 하지 않는 것처럼요.

    아 글고 파티셔닝은 in-place 이기 때문에 memory complexity 에 포함할 수는 없겠죠. 퀵소트의 공간 복잡도는 O(lgN) 이고 머지소트의 공간 복잡도는 O(N) 이라고 하는 것도 같은 데에서 연유합니다. (원본 데이터의 순서를 유지해야 하는 경우라면 안되겠지만)

    그리고, 이거는 researcher 와 단순한 problem solver 로서의 입장 차이이겠지만, 2개로 주어졌던 문제를 generalize 해버리신 후에 애초에 고려하지 않았던 방향에서 제 알고리즘이 시간복잡도가 올라가 버린다고 하시면 전 슬퍼요~ :( 임의의 m개였다면 저도 다른 방법을 생각했을 테니까요. ^^ 그리고 정석류의 정형화된 해법을 원하는 문제라기보단, linear time selection 강의의 연습문제 정도로 나올 문제라고 생각했는데요. :3 문제야 상황에 따른 다양한 애스펙트를 가질 수 있는 것인데.. 그 중의 어떤 부분을 선택하느냐는 개인의 취향이라고 봐요~ 고로 abraxus 님이 제게 짠 점수를 주신다면 저는 강력히 항의할껍니다. :)

  13. abraxsus Avatar
    abraxsus

    :-) ㅎㅎ.. 동의합니다. 입장차이와 approach의 차이라고 봅니다.
    제가 좀 제멋대로 문제를 고치거나 스스로 문제를 만들어내는 경향이-_-;;;;;
    동감입니다. 수업시간의 연습문제같은걸로 나올만한 문제라고 생각해요…
    물론, 제가 정답에 짠 점수를 줄수있는 권한같은것이 있을리 없지요 :-)
    제가 좀 ‘정답’이라는 개념에는 딴지를 거는 편입니다만,
    그 해법 자체는 훌륭하니까요.. :-)

  14. MKSeo Avatar
    MKSeo

    음 일단 제가 보기엔 JM님이 내놓으신 답이 정답입니다. .
    간단하게 그냥 소트해버리면 끝난다는 것도 일리있는 지적이고..
    다들 문제 열심히 풀어주셔서 감사 ^^
    근데 너무 잘들 푸셔서;;;

    그리고, 이 문제 연습문제 아닙니다.
    제가 알기론 모 회사 입사문제라고 어디선가 돌아다니다가 봤는데,
    모회사가 무슨 회사인지는 며느리도 몰라요.

  15. abraxsus Avatar
    abraxsus

    걍 논문보다가.. 이 문제가 일어나는곳은, 이런곳이 있네..
    UDP패킷들을 client가 받았는데, 이게 순서도 엉망이고, 심지어 빠진곳들도 있다는거지..
    이럴대 retransmission을 요청하고 싶은데, missing packet들을 찾아낼 필요가 있으니까,
    이럴때 딱 맞겠는걸.. 이 문제를 모델링해서 문제로 낸걸까??
    걍 생각나서 적어봄…(당연한 거였나-_-;;)

  16. mkseo Avatar
    mkseo

    UDP는 IPv6에선 몰라도 v4에선 패킷 시퀀스 번호가 없잖아.

Leave a Reply

Your email address will not be published. Required fields are marked *