前の65バイトソリューション:
r->{for(int a,b=0,z,i=0;;b=a)if((a=b|1<<(z=r[i++]))==b)return z;}
新しいソリューション。19バイトが含まれていますimport java.math.*;
@Nevayのおかげで-8バイト
r->{int z,i=0;for(BigInteger c=BigInteger.ZERO;c.min(c=c.setBit(z=r[i++]))!=c;);return z;}
オンラインでお試しください!
編集
私の元のプログラムのアルゴリズムは問題ありませんでしたが、使用されたデータ型の静的サイズは、サイズが特定のしきい値を超えるとかなり急速に壊れることを意味しました。
これに対応するために、プログラムのメモリ制限を増やすために計算で使用されるデータ型を変更しました(またはのBigInteger
代わりに任意の精度を使用)。ただし、これがスペースの複雑さとしてカウントされるかどうかは議論の余地があります。int
long
O(1)
以下に説明をそのまま残しますが、O(1)
いくつかの仮定をせずにスペースの複雑さを達成することは不可能だと今私は付け加えたいと思います。
証明
N
などの整数として定義し2 <= N
ます。
ましょうS
一連のランダムな整数を表すリスト[x{1}, ..., x{N}]
であり、どこx{i}
に制約があります1 <= x{i} <= N
。
要素ごとに1回だけこのリストを反復処理するのに必要な時間の複雑さ(Big-O表記)は O(n)
与えられた課題は、リスト内で最初に重複した値を見つけることです。具体的にはS
、リストの前のアイテムの複製である最初の値を検索しています。
させるおよびリスト内の2つの要素の位置p
とq
なるようにp < q
しx{p} == x{q}
ます。私たちの課題は、q
これらの条件を満たす最小のものを見つけることです。
この問題への明白なアプローチは、我々があればSを反復してチェックすることですx{i}
別のリストに存在してT
いる場合は:x{i}
に存在しないT
、我々はそれを保存しますT
。x{i}
がに存在する場合T
、それは最初の重複値であり、したがって最小です。したがって、q
それを返します。このスペース効率はO(n)
です。
時間の複雑O(1)
さを維持しながらスペースの複雑さを達成するにO(n)
は、リスト内の各オブジェクトに関する一意の情報を有限のスペースに格納する必要があります。このため、アルゴリズムが実行できる唯一の方法はO(1)
スペースの複雑さは次の場合です。1. Nには、特定の有限データ型の可能な値の最大数を格納するために必要なメモリに対応する上限が与えられます。2.単一の不変変数の再割り当ては、複雑さに対してはカウントされず、変数の数(リストは複数の変数)に対してのみカウントされます。3.(他の回答に基づいて)リストは変更可能(または少なくともリストの要素は変更可能)であり、リストのデータ型は符号付き整数として事前設定されており、リスト内のさらに要素に変更を加えることができます。追加のメモリを使用せずに。
1と3は両方ともデータ型に関する仮定と仕様を必要とし、2は変数のサイズではなく変数の数のみをスペースの複雑さの計算に考慮することを要求します。これらの仮定がどれも受け入れられない場合、O(n)
時間の複雑さとO(1)
スペースの複雑さの両方を達成することは不可能です。
説明
男の子、これは恥ずかしいほど長い時間をかけて少しの脳力を考え出しました。
そのため、ボーナスを獲得するのは困難です。私たちは、正確に一度、リスト全体で動作するように両方が必要と我々はすでに、追加のスペースの複雑させずに反復処理しました値をトラック。
ビット操作はこれらの問題を解決します。O(1)
整数のペアである「ストレージ」を初期化し、リストを反復処理し、最初の整数のi番目のビットをOR演算し、その結果を2番目の整数に格納します。
たとえば1101
、があり、でOR演算を実行すると10
、が得られ1111
ます。別のORを行う場合10
、まだあり1101
ます。
エルゴ、OR演算を実行して同じ番号になると、重複が見つかりました。配列内に重複がないと、プログラムが実行され、例外がスローされます。