単項関数の値の配列を事前に計算したいと思いますf
。
f(x)
wherex
は の形式の値のみが必要であることはわかっています。ここで、とはa*b
両方ともrange 内の整数です。a
b
0..N
明らかな時間最適化の選択は、サイズの配列を作成し、N*N
後で読み取る要素だけを事前に計算することです。についてf(a*b)
は、チェックして設定するだけtab[a*b]
です。これは可能な限り最速の方法ですが、この配列には ( で始まるN+1
) 決して触れない多数のインデックスがあるため、これは多くのスペースを必要とします。
もう 1 つの解決策は、単純なツリー マップを作成することです。しかし、これは多くの分岐を導入することで、ルックアップ自体を非常に遅くします。いいえ。
私は疑問に思います-そのような配列をスパースでなく小さくする解決策はありますか?
編集
ハッシュマップについて多くのコメントを聞くことができます...どのように動作するかのベンチマークに進みます(分岐により、通常のルックアップよりも大幅なパフォーマンス低下が予想されます;ツリーよりも少ないですが、それでも...そうです!) .
強調したいのは、「製品のような」インデックスのみが取得されるという事実を利用するために、何らかの巧妙な方法 (?) を使用する分析ソリューションを最も高く評価することです。この事実を悪用して、平均的な一般的なハッシュ マップ関数よりも優れた結果が得られる可能性があると思いますが、私自身はアイデアがありません。
編集
std::unordered_map
あなたのアドバイスに従って、 gcc 4.5から試しました。これは、単純な配列ルックアップよりも少し遅くなりましたが、実際にはツリーベースよりもはるかに高速std::map
でした.最終的には、このソリューションで問題ありません. 当初意図していたことができない理由がわかりました。説明をありがとう!
ハッシュマップが実際にメモリを節約するかどうかはわかりません! :) @Keith Randall が説明したように、メモリ フットプリントを よりも低くすることはできず、N*N/4
@Sjoerd によって説明された三角行列アプローチではN*N/2
. N*N/2
要素のサイズが小さい場合 (コンテナーのオーバーヘッドによって異なります) 、ハッシュ マップがスペース以上のものを使用する可能性は十分にあると思います。それを確認してみます。
2つの答えを受け入れることができればいいのに...