web-dev-qa-db-ja.com

複数のベクターと比較してベクター内の一意の要素を見つける効率的な方法

C++を使用して複数のベクターと比較してベクター内の一意の要素の数を見つけようとしています。ベクトルはソートされた順序であり、サイズは2,000,000です。

私が持っているとしましょう

v1: 5, 8, 13, 16, 20
v2: 2, 4, 6, 8
v3: 20
v4: 1, 2, 3, 4, 5, 6, 7
v5: 1, 3, 5, 7, 11, 13, 15

V1の一意の要素の数は1(つまり、16)です。

2つの方法を試しました。

  1. ベクトルv2、v3、v4、およびv5をベクトルのベクトルに追加しました。 v1の各要素について、要素が他のベクトルのいずれかに存在するかどうかを確認します。

  2. マージソートを使用してすべてのベクトルv2、v3、v4、v5を1つのベクトルに結合し、v1と比較して一意の要素を見つけます。

注:sample_vector = v1で、all_vectors_mergedにはv2、v3、v4、v5が含まれています

//Method 1
unsigned int compute_unique_elements_1(vector<unsigned int> sample_vector,vector<vector<unsigned int> > all_vectors_merged)
{
    unsigned int duplicate = 0;
    for (unsigned int i = 0; i < sample_vector.size(); i++)
    {
        for (unsigned int j = 0; j < all_vectors_merged.size(); j++)
        {
            if (std::find(all_vectors_merged.at(j).begin(), all_vectors_merged.at(j).end(), sample_vector.at(i)) != all_vectors_merged.at(j).end())
            {
                duplicate++;
            }
        }
    }
    return sample_vector.size()-duplicate;
}

// Method 2
unsigned int compute_unique_elements_2(vector<unsigned int> sample_vector, vector<unsigned int> all_vectors_merged)
{
    unsigned int unique = 0;
    unsigned int i = 0, j = 0;
    while (i < sample_vector.size() && j < all_vectors_merged.size())
    {
        if (sample_vector.at(i) > all_vectors_merged.at(j))
        {
            j++;
        }
        else if (sample_vector.at(i) < all_vectors_merged.at(j))
        {
            i++;
            unique ++;
        }
        else
        {
            i++;
            j++;
        }
    }
    if (i < sample_vector.size())
    {
        unique += sample_vector.size() - i;
    }
    return unique;
}

これら2つの手法のうち、方法2の方が結果が速いことがわかります。

1)方法1:v1のすべての要素のすべてのベクトルに対してstd :: findを実行するよりも効率的に要素を見つける方法はありますか?.

2)方法2:ベクトルv2、v3、v4、v5を比較してソートする際の追加のオーバーヘッド。

これをより良い方法で行うにはどうすればよいですか?

[編集]ベクトルはソートされた順序になっています。

6
SyncMaster

ハッシュテーブルを使用します。要素がキーで、発生数が値です。

10
ddyer

ソートされているので、標準の std::set_difference 関数:

unsigned int compute_uniqute_elements(vector<unsigned int> sample_vector, vector<unsigned int> merged_vectors)
{
    vector<unsigned int> difference;
    vector<unsigned int>::iterator it;
    it = std::set_difference(sample_vector.begin(), sample_vector.end(), it->begin(), it->end(), difference.begin());

    return std::distance(difference.begin(), it);
}
1
BenjaminB

データは文字列であり、数値を使用して、各ベクトルが並べ替えられているなどの問題の側面をより簡単に説明しているが、反復するベクトルが多数あるようです。

動的プログラミング は、効率を大幅に節約する絶好の機会を提供します。通常、動的プログラミングはアルゴリズムの一部を実行して部分的なソリューションを生成し、後の反復で再利用して時間を節約できます。 巡回セールスマン問題の優れたバージョン があり、これにより大幅な時間の節約になります(大量のメモリが必要になる代わりに)。

データについていくつか知っている場合、たとえば0から99までの整数値に制限されている場合、100のブール値のテーブルを作成し、ベクトルを一度解析してテーブルにマークを付け、どの要素が存在するかを確認するのが簡単な方法です。次に、テストベクトルをテーブルと比較します。

これが検索アルゴリズムであり、入力が複数の文字列のキーであり、並べ替えられた複数のベクトルデータがドキュメントのキーワードである場合、多くの方法から選択して、一意の文字列を binary に適した表現で収集できます。 =または その他の検索 。このヘルパーデータ構造に必要なストレージは、入力データセット内の一意の文字列の数によって異なります。英語のテキストのように多様なデータでさえ、それぞれ数百の単語の200万のベクトルで一意の文字列がわずかしか見つからないのは驚くべきことです。

0
DeveloperDon