web-dev-qa-db-ja.com

キー値に基づく値の範囲

特定の範囲に一致する2Dポイントを大量に検索する方法を実装しようとしています。 <X, Point>および<Y, Point>のHashMapを作成することを考えていますが、x_minからx_maxおよびy_minまでの値に基づいて範囲内のポイントを取得するので、これを行うにはHashMapが適していると思いますy_maxに。

したがって、基本的には<X,Point>からx_minからx_maxまでのすべてのポイントを取得し、<Y,Point>からy_minからy_maxまでのポイントと比較します...

HashMap<Integer,Point> x_coordinates = new HashMap<Integer,Point>();
for(int i=x_min;i<=x_max;i++){
    if(x_coordinates.containsKey(i))
        x_coordinates.get(i);
}

HashMap<Integer,Point> y_coordinates = new HashMap<Integer,Point>();
for(int i=y_min;i<=y_max;i++){
    if(y_coordinates.containsKey(i))
         y_coordinates.get(i);
}

HashMapや他のタイプのデータ構造から値の範囲を取得するより速い方法はありますか?

たとえば、範囲= 200の場合、x-200からx + 200およびy-200からy + 200の範囲に一致するすべてのポイントを選択します

私はすべてのポイントの反復を回避しようとしていますが、問題のポイントが広い領域に散らばっているので、巨大な2D行列を作成することも避けたいです。


いくつかのテストの後、MichaelTの回答に基づいて、次のコードを記述しました。

TreeMap<Integer, TreeMap<Integer, Integer>> values;
for (int x : values.subMap(x_min, x_max).keySet()) {
        for (int y : values.get(x).subMap(y_min, y_max).values()) {
            // y here, represents the values of points in range...
        }
    }
4
Ubica

あなたが説明しているのは、範囲選択を行いたい 疎行列 です。

最初は、HashMapもLinkedHashMapもあなたが望んでいることを最適に行うことはできません。これがHashMapの範囲内の要素を見つける理由は、順序付けられていないリストO(n)を効率的に歩くためです。 LinkedHashMapは、ひどいifよりもわずかに最適である可能性があります。その後、新しいものは追加されません。 O(n)の代わりに、O(n/m)を取得しているため、これはまだ最適なアプローチではありません。範囲を過ぎる)これはまだ実質的にO(n)です。LinkedHashMapリストでバイナリ検索を実行することはできません。

それでは、他のいくつかの構造を見てみましょう。あなたが本当にの後は SortedMap インターフェースです。 SortedMap subMap(K fromKey、K toKey) を使用して、サブマップをあるキーから別のキーにすばやく引き出すことができます。それらのクラスのいずれかを選択すると、あなたはあなたが求めているものを手に入れるでしょう。

次に、各サブマップの values を取得し、あるセットを他のセットに対して boolean retainAll(Collection c) を実行します。

それは簡単な答えです。これは、スパース行列の リストのリスト アプローチです。ただし、より直接的なサブ範囲オプションを提供する他の形式でマトリックスをエンコードすることもできます。これは、Java標準ライブラリの一部ではありません。その場合、独自の実装を作成するために this path にダウンする可能性があります。

将来的に可能性が発生する可能性がある場合は、スパースマトリックス用の独自のインターフェイスを作成し、その背後にあるルックアップを実行するクラスを実装することを検討する必要がありますあなたが欲しい。このようにして、後で何らかの理由で実装を変更する必要があると判断した場合、別の構造を処理するようにすべてのコードを変更するのではなく、実装(他のものをラップする新しいクラス)を変更するだけです。

5
user40980

ツリーマップのツリーマップに基づくソリューションは機能し、最初に使用したハッシュマップソリューションよりもはるかに優れていますが、ツリーマップに似た構造であるが、ペアのキーとしてだけでなく、キーとして調整します。これにより、長方形の範囲をそれらから選択することが特に効率的になります。 Javaで利用可能な多くの実装があり、クイックグーグルで見つけることができます。

2
Jules

k-d tree を確認する必要があります。この構造は、通常、「このポイントは存在しますか?」、「最寄りの郵便局はどこですか?」、「30歳から40歳までの従業員は誰ですか?

したがって、問題は、この構造が特に適している典型的な範囲検索問題です。 Wikipediaによると、この構造での問題の最悪の場合の時間はO(kN ^(1 1/k))です。ここで、kは次元の数(2)で、Nは数です。ツリー内のノードの。

ただし、いくつかの制限があります。

私はそれを使用したことがありませんが、明らかに Java ML にはk-dツリーの適切な実装があります。

0
mgoeminne