2012-04-28 12 views
1

これは学校の割り当てですが、プログラムは「最大のパフォーマンスで実装されている」という要件でした。メモリがスピードを上回るかどうかなど知っているだろう。しかし、私が探しているのは、入力データに対してスマートな操作を行うことで問題を解決する "トリッキーな"方法があるかどうかである。整数が整数の和の1つであるかどうかを調べる効率的な方法

だから、ここで問題があります:A.

の任意の2つの 以降の要素の和に等しいBでこのような整数がある場合は1を返す関数を、書く、あなたは二つの配列、AとBを持って考えます

以下は私の書き上げです。 Hashmap<Integer>を使用しなかったことに注意してください。なぜなら、スピードアップに必要なメモリは、O(n * m)のスピードでO(n *)の代わりに最悪の場合のスピードで十分に不利なものだと考えていたからです。

public static int arrayContainsSum(int[] a, int[] b) 
{ 
    int offsetA = a.length - 1; 
    int offsetB = offsetA; 
    int index = b.length - 1; 
    int result = 0; 
    int tested; 

    while (index >= 0) 
    { 
     if (offsetA > 0) a[offsetA] += a[--offsetA]; 
     else if (offsetA == 0) // This has a danger of overflowing the int 
      a[offsetA--] = multiply(a); 
     tested = b[index]; 
     if ((offsetA < 0 && tested != 0 && a[0] % tested != 0) || 
      offsetB == 0) 
     { 
      // No point to test this element as it doesn't 
      //divide the product of sums 
      offsetB = a.length - 1; 
      index--; 
     } 
     if (tested == a[offsetB--]) 
     { 
      result = 1; 
      break; 
     } 
    } 
    return result; 
} 

private static int multiply(int[] input) 
{ 
    int accumulator = input.length > 0 ? 1 : 0; 
    for (int i : input) 
     if (i != 0) accumulator *= i; 
    return accumulator; 
} 

私が心配していないことがいくつかあります:整数のオーバーフロー(乗算の結果として起こりうる)。私はarray.lengthがローカル変数からの読み込みと同じくらい速いと仮定しました。

しかし、私の質問はむしろ「分析的にこの問題を解決することはできませんでしたか?より良い効率を意味するでしょうか?

PS。この問題には、配列にユニークなメンバーしか含まれていないことは言及されていません。私はまた、aをソートすることによって最適化することが可能であると考えているので、がaの最小要素より小さく、次にaの最大要素よりも小さい場合は、いくつかのルックアップを保存します。これもまた複雑さが増し、恐らく完全に正当化されないであろう。

+0

私はあなたの質問が何を意味するか分かりません。この場合、分析的にはどういう意味ですか? –

+1

O(1)メモリでこれを行いたい場合は、配列をソートしてバイナリ検索を行う方が良いでしょう(aとbは配列のサイズです):O(a * b) a + b * log a)である。 a == bの場合は、O(a^2)とO(aログ)です。最適なアルゴリズムは、あなたがすでに知っているように、O(a)余分なメモリを持ちますが、O(b)時間で実行されます。 – Voo

+2

私は何故乗算を呼び出す必要があるのか​​理解できないと言わなければなりません(あなたのコードが何をしているのか分かりませんでしたが、これは私の目立つものです...) –

答えて

1
public static int arrayContainsSum(int[] a, int[] b) { 
    final Set<Integer> sums = new HashSet<Integer>(); 
    for (int i = 0; i < a.length - 1; i++) sums.add(a[i] + a[i+1]); 
    for (int x : b) if (sums.contains(x)) return 1; 
    return 0; 
} 
+0

2つの配列の長さが非常に異なっていて、長い配列があらかじめわかっていない場合は、まず長い配列をチェックして、その配列をHashSetに入れ、もう1つをループでスキャンします。 –

+0

実際には違いはありません。解は 'O(a + b)'であり、他方は全く同じです。実用的な目的でさえ、「追加」と「包含」との間の差異は無視できるものでなければならない。唯一の利点は、スペースのreqsを 'O(a)'から 'O(min(a、b、))'に変更することです。 – Voo

+0

はい、その間にそれについて考えても、同じ結論に達しました。 'add'または' contains'のどちらかが他のものを支配している場合は、ハッシュテーブルに入れる方を短くするか長い方を選ぶのが理にかなっていますが、似ています。私が得たもう一つのアイデアは、使用される整数の範囲が比較的小さいことが分かっている場合に、 'BitSet'を使うことです。 –

0

要素が100万を超え、1秒以上かかる場合を除き、速度は関係ありません。 Btwでは、100万個以上の要素の配列を作成する必要はありません。

7までのJavaバージョンには、基本的な設定操作さえありません。しかし、それらはGoogle Guavaライブラリで見つけることができます(そのコードは適切にテストされ、できるだけ効率的です)。

あなたは2組の20個の要素、ab考えてみましょう - あなたが見つけたいその後1から100までのランダムで選択され、200

a = RandomInteger[{100}, 20] 
b = RandomInteger[{200}, 20] 

を何のa和の集合の要素後続の要素は、例えばb

ap = Table[Total[{a[[i]], a[[i + 1]]}], {i, 1, Length[a] - 1}] 
Intersection[ap, b] 

と交差:

{73,43,99,33,80,35,54,82,50,23,92,22,54,4,14,14,8,80,92,85} 
{121,139,158,158,51,176,65,84,76,172,73,148,71,128,55,134,4,32,183,134} 
{116,142,132,113,115,89,136,132,73,115,114,76,58,18,28,22,88,172,177} 
{73,76,172} 
+0

交差点は過剰です。 OPには存在が必要です。 –

+0

もし私が最悪の場合と誤解していないなら、彼は 'Length [交差点[ap、b]]'が0かどうかを調べる必要があります。 – Margus

+0

交差点を計算せずに長さが0であることを証明できる場合は、交差点を計算していません。私は交差点を計算することは残酷だと言った。 –

0

不確かな場合は、ブルートフォースを使用してください。

もちろん、実行可能なソリューションを作成するタスクであれば、これでは不十分かもしれませんが、ソリューションを最適化する前に解決策が必要です。

val a = List (3, 9, 7, 4, 16)  
val b = List (29, 12, 21, 16, 18, 14) 

for (i <- (0 to a.length - 2); 
    j = i+1; 
    if b.exists (_ == a(i)+a(j))) yield (a(i), a(j), a(i)+a(j)) 

どのくらいの頻度で実行されますか? 外側のループは、1から配列長さ-1(ここではリストです)を実行してi、jを生成します。

しかし、それはあなたがソート値によるBならば、あなたはBでバイナリ検索を行うことができ、全体アレイ、

を通じて常に走るBの。 2つの配列が与えられているので、HashMapはルールから許可されていないと思います。それ以外の場合、HashMapは高速です。

+0

これはおそらく時間と空間の最適なバランスですが、ソートを必要としないハッシュテーブルを持つソリューションより必ずしも優れているとは限りません。 –

+0

@wvxvw:私は最初の投稿にばかげた間違いをしました。要素は後で1つの配列になければならないので、ソートすることはできません。ハッシュマップが許可されている場合、それは最も速くなります。しかし、ソートされた配列は高速でバイナリ検索することができます。 –

関連する問題