2009-03-18 5 views
4

私は猫の誕生日でソートJava:ソートされたリスト内の要素を見つける最良の方法は何ですか?

List<Cat> 

を持っています。 1983年1月24日に生まれたすべての猫を見つけるための効率的なJava Collectionsの方法はありますか?あるいは、一般的にどのような良いアプローチですか?

+0

私は回答を提出しようとしていましたが、binarySearchは最初の結果を返すことが保証されていないため、その回答はウィンドウの外に出ました。 – Powerlord

答えて

9

Collections.binarySearch()

猫が誕生日によってソートされていると仮定すると、正しい誕生日の猫のインデックスが表示されます。そこから、あなたは誕生日の異なる1つを押すまで前後に繰り返すことができます。

リストが長く、誕生日を共有していない猫が多い場合、これはストレート反復に比べて大きな勝利になるはずです。

ここに私が考えているコードの種類があります。私はrandom-accessのリストを仮定しています。リンクされたリストの場合、あなたはかなり反復に固執しています。 (コメントでこれを指摘してフレッド-Oに感謝します。)

List<Cat> cats = ...; // sorted by birthday 
List<Cat> catsWithSameBirthday = new ArrayList<Cat>(); 
Cat key = new Cat(); 
key.setBirthday(...); 
final int index = Collections.binarySearch(cats, key); 
if (index < 0) 
    return catsWithSameBirthday; 
catsWithSameBirthday.add(cats.get(index)); 
// go backwards 
for (int i = index-1; i > 0; i--) { 
    if (cats.get(tmpIndex).getBirthday().equals(key.getBirthday())) 
     catsWithSameBirthday.add(cats.get(tmpIndex)); 
    else 
     break; 
} 
// go forwards 
for (int i = index+1; i < cats.size(); i++) { 
    if (cats.get(tmpIndex).getBirthday().equals(key.getBirthday())) 
     catsWithSameBirthday.add(cats.get(tmpIndex)); 
    else 
     break; 
} 
return catsWithSameBirthday; 
+0

Collections.binarySearch()は単一の要素を返し、同一とみなされる要素については保証しません。 – Jake

+0

多分それは私に答える前に質問を読むように教えてくれるでしょう。 :) –

+0

また、Collections.binarySearch()はランダムアクセスリストに対してのみ有効です。 –

6

バイナリ検索が行くための古典的な方法です。

説明:バイナリ検索を使用しています。具体的な方法はありません。アルゴリズムは次のとおりです。

//pseudocode: 

index = binarySearchToFindTheIndex(date); 
if (index < 0) 
    // not found 

start = index; 
for (; start >= 0 && cats[start].date == date; --start); 
end = index; 
for (; end < cats.length && cats[end].date == date; ++end); 

return cats[ start .. end ]; 
+0

Collections.binarySearch()は単一の要素を返し、同一とみなされる要素について保証しません。 – Jake

+0

私は 'Collections.binarySearch'メソッドを使うべきではないと言いました。 1つの要素のインデックスを検索するバイナリ検索。誕生日が等しい他の要素はすべて、見つかった要素の横にあります。 1つのループですべてを得ることができます。それは古典です。 –

+0

@Mehrdad - これを反映する答えを更新すると、アップヴォートを獲得できます。 – slim

0

あなたは何とか日付でコレクションのインデックスを作成しない限り、あなたは本当に速い検索と誕生日とHashMapを使用する必要がある場合は、唯一の方法は、それらのすべて

+0

日付でソートされています。おそらくあなたはインデックスと呼ぶだろうか? –

+0

私はそれが*唯一の方法であるとは思わない。確かに、あなたは与えられた誕生日を持つ猫の最初の出現を見つけてそこから直線的に進むことによってこれを非常に効率的に行う「低レベル」アルゴリズムを想像することができます。 – Jake

+0

Jake:何らかのアルゴリズムがあれば、バイナリ検索をしない限り、最初の要素はO(n)になります。漸近的に最速のアルゴリズムは、バイナリ検索で、それ以降の開始点と終了点を線形に探し出すことです。 –

0

を反復処理することであろうキー。キーをソートする必要がある場合は、TreeMapを使用します。

複数のネコが同じ誕生日を持つことを許可したいので、Hast/TreeMapの値としてコレクションを使用する必要があります。

 Map<Date,Collection<Cat>> 
3

Google Collections述語を使用して述語が日付に一致するフィルター処理されたコレクションを作成することによって、あなたがやりたいことができます。

+0

O(n)のCollectionをフィルタリングしますか? – Jake

+0

私はそれが各要素に述語を適用するので、そうする必要があると仮定します。リストがソートされている場合は、バイナリ検索(上向きの回答と同様)が最適です。 – basszero

関連する問題