2012-03-12 15 views
11

今日、インタビュアーは私にこの質問をしました。私の即時の対応は、現在の要素と配列内の前の要素を比較するだけで、線形検索を行うことができたということでした。彼はその後、問題が線形ではない時間にどのように解決できるかを私に尋ねました。直線的でない時間では、ソートされた配列で複製を見つける

仮定

  • アレイ複製のみアレイのみnでの長さ数[0, n]、移入ある
  • あり
  • をソートされアレイ。

例アレイ:[0,1,2,3,4,5,6,7,8,8,9]

Iは分割統治を思い付くしようとしこれを解決するアルゴリズムはありますが、それが正しい答えであるとは確信していません。誰にもアイデアはありますか?

+1

この例では、数値[0、n-2]のみが含まれています(「10」はありません) 、 '11')それは単なる例か一般的な規則ですか? – jfs

答えて

23

は修正バイナリサーチと(Nログ)Oで行うことができる:

スタートアレイの中央に:アレイは[IDX] < IDX重複がそうでなければ、右へ、左にある場合。すすぎ、繰り返します。

+0

ジェネリック版の場合、 'array [idx] -array [0]'にする必要があります。 – user

5

私はこれを解決するために分裂征服アルゴリズムを考え出しましたが、正しい答えではないと確信しています。

確かに、バイナリ検索を行うことができます。

arr[i/2] >= i/2の場合、複製はアレイの上半分に配置され、それ以外の場合は下半分に配置されます。 lowerupper間のアレイは、各反復において半分にされているので

while (lower != upper) 
    mid = (lower + upper)/2 
    if (arr[mid] >= mid) 
     lower = mid 
    else 
     upper = mid-1 

は、アルゴリズムは、O(Nログ)で実行されます。

ideone.com demo in Java

+0

[in Python](http://ideone.com/YHf9i) – jfs

7

全く数がアレイから欠落していない場合は、例のように、それはバイナリサーチで(ログn)Oでなんとかです。 a[i] < iの場合、複製はiの前になり、それ以外の場合はiの後になります。

不在つの数字と1個の重複がある場合、我々はまだa[i] < i場合、重複はi前でなければならず、a[i] > i場合、欠席数はiと後に重複する前でなければならないことを知っています。ただし、a[i] == iの場合は、番号が見つからない場合は、iまたはその両方の前に番号と重複が両方ともあるかどうかはわかりません。iの後です。その場合、私はサブ線形アルゴリズムのための方法を見ません。

+0

私は非常に遅いですが、欠落した数を許可すると、実際には不可能です(あなたがO(1)内の任意の数のセル))。サイズn + 1(n> = 2)のエントリを考え、エントリのこのサブセットに自分自身を限定するとします。{[0,0,2、...、n]、[0,1,1,3、...、n ]、[0,1、...、k、k、k + 2、...、n]、...、[0,1、...、n-1、n-1]あなたがすでに(n-2)までの細胞の内容を知っていて、それらがペアで区別されていると仮定しましょう。まだ少なくとも2つの可能性があり、あなたはそれを差別することはできません。したがって、少なくとも(n-1)個のセルを読み取って、重複するセルの数を判断する必要があります。 – Caninonos

0

例の配列はあなたの質問と少し異なります。 nは配列の長さであり、配列中に唯一の重複があるので、配列内の各要素の値は[0、n-1]でなければなりません。それが本当であれば

は、この質問はO(n)の時間とO(1)スペース内の重複を見つける必要がありHow to find a duplicate element in an array of shuffled consecutive integers?

次のコードと同じものです。

public static int findOnlyDuplicateFromArray(int[] a, boolean startWithZero){ 
    int xor = 0; 
    int offset = 1; 
    for(int i=0; i < a.length; i++){ 
     if(startWithZero) 
      xor = xor^(a[i] + offset)^i; 
     else 
      xor = xor^a[i]^i; 
     } 
     if(startWithZero) 
      xor = xor - offset; 
    return xor; 
} 
+0

申し訳ありませんが、これはあまり直線的ではありません。バイナリ検索を使用して目標を達成する必要があります。 – user1106083

0

どうですか? 0からn-1までの自然数の所定のアレイ素子との和の和との間の(再帰スタイル)

public static int DuplicateBinaryFind(int[] arr, int left, int right) 
{ 
    int dup =0; 

    if(left==right) 
    { 
     dup = left; 
    } 
    else 
    { 
     int middle = (left+right)\2; 
     if(arr[middle]<middle) 
     { 
      dup = DuplicateBinaryFind(arr,left, middle-1); 

     } 
     else 
     { 
      dup = DuplicateBinaryFind(arr, middle+1, right); 
     } 
    } 

    return dup; 

} 
1

違いはあなた重複要素を与えます。 0からn-1要素の和は(N * N-1)/ 2 です。例配列は[0,1,2,3,4,5,6,7,8,8,9] の合計です。 45 配列要素の合計:53 53-45 = 8複製された要素はどれですか

+0

すべての要素を加算するのはO(n)なので、予算超過 – tucuxi

関連する問題