整数A
とB
(サイズが)A
以下の2つのセットがあり、「どれくらい近いか」B
という質問に答えたいと思います。私がこの質問に答えたい方法は、inを見つけるために与えられたinからどれだけ遠くまで行かなければならないかの尺度を作成することです。 A
B
a
A
b
B
私が作成したい特定のメジャーは次のことを行います。それぞれa
について、最も近いものを見つけます。b
唯一のキャッチは、aをと一致させるb
と、それを使用して他のを一致させるa
ことができなくなることです。(編集:私が実装しようとしているアルゴリズムは、常に短い一致を優先します。したがって、が複数に最も近い場合は、最も近いものを選択してください。複数が同じ距離にある場合はどうすればよいかわかりません。に、今私は前にあるものを選んでいますb
a
b
a
a
b
a
b
a
b
、ただし、これは非常に恣意的であり、必ずしも最適ではありません。)最終製品であるこれらのセットを作成するための測定値は、縦軸にペアの数、x軸にペアの距離を示すヒストグラムです。
したがって、A = {1, 3, 4}
との場合、B = {1, 5, 6, 7}
次のa,b
ペアを取得します:1,1
、、。これらのデータの場合、ヒストグラムには、距離が0のペア、距離が1のペア、距離が3のペアが表示されます。4,5
3,6
(これらのセットの実際のサイズには約100,000要素の上限があり、すでに低から高にソートされているディスクから読み込みます。整数の範囲は1から〜20,000,000です。編集:また、との要素A
はB
一意です。つまり、繰り返される要素。)
私が思いついた解決策は少し不格好に感じます。私はPerlを使用していますが、問題は多かれ少なかれ言語に依存しません。
まず、ハッシュを作成します。との和集合に表示される数値ごとに1つのキーと、各数値が、、、
A
または両方にB
表示されるかどうかを示す値を使用します。たとえば、数値5が両方のデータセットに表示される場合などです。(にのみ表示された場合は、があります。)A
B
$hash{5} = {a=>1, b=>1}
A
$hash{5} = {a=>1}
次に、とに
A
表示されるすべてのハッシュ要素を繰り返して検索し、メジャーでそれらをマークして、ハッシュから削除します。A
B
次に、すべてのハッシュキーを並べ替えて、ハッシュの各要素がリンクリストのように最近傍を指すようにします。ここで、特定のハッシュ要素はのようになり
$hash{6} = {b=>1, previous=>4, next=>8}
ます。A
リンクリストは、次の要素と前の要素がにあるか、にあるかを認識していませんB
。次に、で始まるペアの距離をループし
d=1
、距離のあるすべてのペアを見つけてd
マークを付け、一致する要素がなくなるまでハッシュから削除しますA
。
ループは次のようになります。
for ($d=1; @a > 0; $d++) {
@left = ();
foreach $a in @a {
$next = $a;
# find closest b ahead of $a, stop searching if you pass $d
while (exists $hash{$next}{next} && $next - $a < $d) {
$next = $hash{$next}{next};
}
if ($next is in B && $next - $a == $d) {
# found a pair at distance $d
mark_in_measure($a, $next);
remove_from_linked_list($next);
remove_from_linked_list($a);
next;
}
# do same thing looking behind $a
$prev = $a;
...
# you didn't find a match for $a
push @left, $a;
}
@a = @left;
}
b
このループは明らかに、'sより後に表示される'sに一致するペアを優先しa
ます。後が前よりも優れているかどうかを判断するための賢明な方法があるかどうかはわかりません(ペアを近づけるという点で優れています)。私が興味を持っている主な最適化は処理時間です。