100万の配列があって、中には2つの繰り返しがあって、どのようにアルゴリズムを設計して見つけます
出力:2つの重複する要素のインデックス
まず、直接二重ループで検索するのはだめではなく、最も愚かな方法だと思います.
次に、まずクイックソートで撮って、それから遍歴して、時間の複雑度が一番いいのは最悪の場合nlogn+nです.
hashを使う人もいれば、ビットマップを使う人もいて、どんな状況なのか分からないので、使うのが面倒だと思います.
実は最も考えたいのはHashSet方式で、数がそれほど多くない場合は大丈夫で、100万同時メモリにロードするのは受け入れられ、主に時間の複雑さを考慮します.
コードは次のとおりです.
ここでは2番目に繰り返される要素だけを印刷し、前を探す必要がある場合は、HashSetにindex/valueを含むオブジェクトを格納し、繰り返されるvalueを見つけた後、valueを比較することでindexを取得するなど、より多くの操作が必要です.ここでは、遍歴するプロセスを追加する必要があります.
HashMapの実装プロセスをシミュレートし、次のコードを示します.
HashCodeハッシュが比較的良く,最良の場合はチェーンテーブル操作を必要としない場合,アルゴリズム全体の時間的複雑度はO(n)であり,最悪の場合HashCodeはハッシュが全く開かず,時間的複雑度はO(n^2)である.
もちろんここではHashMap方式を用いて実現してもよいが,valueをkey,indexをvalueとし,containsKey法により現在そのkeyが存在しているか否かを判断し,既に存在すれば直接取り出すことが目的となる.
もし自分で何かをしなければならないなら、Hashの考えを通じて:
各要素配列がばらばらで重複していないと仮定すると,このときの時間複雑度は最も高いのではないか.問題はHashCodeが絶対に繰り返さないことをどのように保証するかです.
未完待機・・・
まず、直接二重ループで検索するのはだめではなく、最も愚かな方法だと思います.
次に、まずクイックソートで撮って、それから遍歴して、時間の複雑度が一番いいのは最悪の場合nlogn+nです.
hashを使う人もいれば、ビットマップを使う人もいて、どんな状況なのか分からないので、使うのが面倒だと思います.
実は最も考えたいのはHashSet方式で、数がそれほど多くない場合は大丈夫で、100万同時メモリにロードするのは受け入れられ、主に時間の複雑さを考慮します.
コードは次のとおりです.
int a[] = { 6, 4, 18, 10, 24, 8, 9, 16, 19, 13, 25, 15, 12, 11, 2, 0,
14, 17, 12, 5 };
int n = a.length;
Set intSet = new HashSet();
for (int i = 0; i < n; i++) {
if (!intSet.add(a[i])) {
System.out.println(a[i]);
break;
}
}
ここでは2番目に繰り返される要素だけを印刷し、前を探す必要がある場合は、HashSetにindex/valueを含むオブジェクトを格納し、繰り返されるvalueを見つけた後、valueを比較することでindexを取得するなど、より多くの操作が必要です.ここでは、遍歴するプロセスを追加する必要があります.
HashMapの実装プロセスをシミュレートし、次のコードを示します.
public void testFindRepeatInt2() {
int a[] = { 6, 4, 18, 10, 24, 8, 9, 16, 19, 13, 25, 15, 12, 11, 2, 0,
14, 17, 12, 5 };
int n = a.length;
IndexValue iv[] = new IndexValue[n];
IndexValue target = null;
for (int i = 0; i < n; i++) {
if (null != (target = put(a, i, iv))) {
System.out.println(" :a【" + target.index + "】=="
+ target.value);
System.out.println(" :a【" + i + "】==" + a[i]);
break;
}
}
System.out.println(Arrays.toString(iv));
}
private IndexValue put(int[] a, int i, IndexValue[] iv) {
int index = a[i] % iv.length;
IndexValue target = null;
if (iv[index] == null) {
iv[index] = new IndexValue(i, a[i]);
} else {
IndexValue temp = iv[index];
if (null != (target = contains(temp, a[i]))) {
return target;
} else {
IndexValue newIv = new IndexValue(i, a[i]);
newIv.next = temp;
iv[index] = newIv;
}
}
return target;
}
private IndexValue contains(IndexValue temp, int value) {
if (temp.value == value) {
return temp;
}
if (temp.next != null) {
return contains(temp.next, value);
}
return null;
}
class IndexValue {
int index;
int value;
IndexValue next;
public IndexValue(int index, int value) {
super();
this.index = index;
this.value = value;
}
@Override
public String toString() {
return "IndexValue [index=" + index + ", value=" + value
+ ", next=" + next + "]";
}
}
ここの要素はすべてintタイプであるため、データハッシュを行う場合、ここでは図の都合上hashCodeを取らず、Stringまたは他のタイプであればHashCodeを用いてハッシュを行うことができる.HashCodeハッシュが比較的良く,最良の場合はチェーンテーブル操作を必要としない場合,アルゴリズム全体の時間的複雑度はO(n)であり,最悪の場合HashCodeはハッシュが全く開かず,時間的複雑度はO(n^2)である.
もちろんここではHashMap方式を用いて実現してもよいが,valueをkey,indexをvalueとし,containsKey法により現在そのkeyが存在しているか否かを判断し,既に存在すれば直接取り出すことが目的となる.
もし自分で何かをしなければならないなら、Hashの考えを通じて:
各要素配列がばらばらで重複していないと仮定すると,このときの時間複雑度は最も高いのではないか.問題はHashCodeが絶対に繰り返さないことをどのように保証するかです.
未完待機・・・