(同じ配列を)複数回検索する必要がある場合は、元のインデックスと値を組み合わせた一時的な構造を作成できます。
class Pair implements Comparable<Pair> {
final int index;
final int value;
Pair(int index, int value) {
this.index = index;
this.value = value;
}
public int compareTo(Pair oth) {
if (value < oth.value) return -1;
else if (value > oth.value) return 1;
else if (index < oth.index) return -1;
else if (index > oth.index) return 1;
else return 0;
}
}
final ArrayList<Pair> list = new ArrayList<Pair>();
for (int k = 0; k < array.length; ++k) {
list.add(new Pair(k, array[k]);
}
Arrays.sort(list);
ここで、list
値、次にインデックスで並べ替えられます。これで、(たとえば)バイナリ検索を使用して要素を検索できます。ただし、これは価値があるだけであることに注意してください。回数、値を検索する場合(現在O(log n)
はではなくO(n)
)、配列の構築にかかる時間((O(n log n)
並べ替えのため)が支配的です。
HashMap
または、またはを使用してインデックスのような構造を構築することもできますTreeMap
。これは、整数値から配列内のその位置にマップされます。を使用する場合HashMap
、アクセス時間は、上記で提案された二分探索アプローチO(1)
の場合と同様に、約にTreeMap
なります。O(log n)
これらの提案はすべて、配列を頻繁に検索する必要がある場合にのみ、明らかに価値があります。
また、配列が適度に小さい場合は、(他の人が提案しているように)単純な線形検索を使用することが、関連する「定数」が低く、配列コンポーネントの局所性が高いため、実際には最速の解決策になる可能性があることを考慮する必要があります。
したがって、さらに別のアプローチは、Pair
2つの整数配列(1つは値を含み、もう1つはインデックスを含む)にソートした後、構造を再度解凍することです。
int[] values = new int[list.size()];
int[] indices = new int[list.size()];
int pt = 0;
for (Pair p: list) {
values[pt] = p.value;
indices[pt] = p.index;
pt += 1;
}
これで、values
バイナリ検索を使用して配列を検索できます。
int position = Arrays.binarySearch(values, valueToLookFor);
if (position >= 0) {
// Found it!
int index = indices[position];
System.out.println("Value was originally stored in " + index);
} else {
// Value not found
}
覚えておいてください:配列のサイズとエントリを検索する必要がある回数によっては、最も単純なソリューション(線形スキャン)が最も速い場合があります。私は実際にそれを最初に試し、それがボトルネックであることが判明した場合は、より複雑な提案の1つのみを使用します。