簡體   English   中英

如何映射/索引向量(整數)以便快速訪問和比較c ++

[英]How to map/ index vectors(of integers) for fast access and comparison c++

我有一個int矢量向量增長非常大(有意)。

vector<vector<int>> coinGroups;

在我的算法的每一步中,我嘗試將每個(int的向量)彼此組合。 對於要傳遞並被添加到向量矢量以進行下一個循環迭代的組合,它必須通過三個標准,其中兩個是超快速且在這里不相關,但是慢的是我的問題:

頭必須匹配尾巴:

//bool match = equal(coinGroups.at(i).begin()+1, coinGroups.at(i).end(), coinGroups.at(ii).begin());

在視覺上,這將(a,b,c,d)與(e,f,g,h)比較為b == e && c == f && d == g

*我嘗試使用int的向量作為關鍵...但這是超級慢的(我假設我做錯了)

這是一個獨立的.cpp,如果有人需要它或更有意義:

參數什么都不是(默認為12 12)或兩個空格分隔的整數大於3(預警這個算法是O(n!)復雜度)

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <map>
#include <sstream>

using namespace std;

//min clock size 3
vector<vector<int>> placeCoins(int _clockSize, vector<int> _coins)
{
    int totalCheckedCombos = 0;
    vector<vector<int>> coinGroups;
    vector<int> coinSet = _coins;
    sort(coinSet.begin(), coinSet.end());
    coinSet.erase(unique(coinSet.begin(), coinSet.end()), coinSet.end());

    map<int, int> coinCounts;
    for (int i = 0; i < coinSet.size(); i++)
    {
        coinCounts[coinSet.at(i)] = count(_coins.begin(), _coins.end(), coinSet.at(i));
    }

    cout << "pairs" << endl;
    //generate fair pairs of coins
    for (int i = 0; i < coinSet.size(); i++)
    {
        for (int ii = 0; ii < coinSet.size(); ii++)
        {
            if ((coinSet.at(i) + coinSet.at(ii)) % _clockSize != 0)
            {
                if (i == ii)
                {
                    if (coinCounts[coinSet.at(i)] > 1)
                    {
                        coinGroups.push_back({ coinSet.at(i),coinSet.at(ii) });
                    }
                }
                else
                {
                    coinGroups.push_back({ coinSet.at(i),coinSet.at(ii) });
                }
            }
        }
    }

    cout << "combine" << endl;
    //iteratively combine groups of coins
    for (int comboSize = 3; comboSize < _clockSize; comboSize++)
    {
        totalCheckedCombos += coinGroups.size();
        vector<vector<int>> nextSizeCombos;
        for (int i = 0; i < coinGroups.size(); i++)
        {
            for (int ii = 0; ii < coinGroups.size(); ii++)
            {
                //check combo to match

                //cleaner but slower due to inability to breakout early on compare check
                //bool match = equal(coinGroups.at(i).begin()+1, coinGroups.at(i).end(), coinGroups.at(ii).begin());

                bool match = true;
                for (int a = 0; a < comboSize - 2; a++)
                {
                    if (coinGroups.at(i).at(a+1) != coinGroups.at(ii).at(a))
                    {
                        match = false;
                        break;
                    }
                }

                //check sum
                if (match)
                {
                    vector<int> tempCombo = coinGroups.at(i);
                    int newVal = coinGroups.at(ii).at(coinGroups.at(ii).size()-1);
                    tempCombo.push_back(newVal);
                    if (coinCounts[newVal] >= count(tempCombo.begin(), tempCombo.end(), newVal))
                    {
                        if (accumulate(tempCombo.begin(), tempCombo.end(), 0) % _clockSize != 0)
                        {
                            nextSizeCombos.push_back(tempCombo);
                        }
                    }
                }
            }
        }

        if (nextSizeCombos.size() == 0)
        {
            //finished, no next size combos found
            break;
        }
        else
        {
            cout << nextSizeCombos.size() << endl;
            coinGroups = nextSizeCombos;
        }
    }
    cout << "total combos checked: " << totalCheckedCombos << endl;
    return coinGroups;
}

//arguments are _clockSize _coinCount
//The goal of this algorithm is to create combos of stepSizeTokens (coins) which fill a loop of register locations (clock)
int main(int argc, char *argv[]) {
    int clockSize = 12;
    int coinCount = 12;

    if (argc >= 2)
    {
        std::istringstream iss(argv[1]);
        if (!(iss >> clockSize))
        {
            cout << "argument 1 invalid" << endl;
            cout << "press enter to end program" << endl;
            cin.get();
            return 0;
        }
        std::istringstream iss2(argv[2]);
        if (!(iss2 >> coinCount))
        {
            cout << "argument 2 invalid" << endl;
            cout << "press enter to end program" << endl;
            cin.get();
            return 0;
        }
    }

    if (clockSize < 3) { clockSize = 3; }

    vector<int> coins = {};
    cout << "coin list:" << endl;
    for (int i = 0; i < coinCount; i++)
    {
        int tempCoin = rand() % (clockSize - 1) + 1;
        cout << tempCoin << " , ";
        coins.push_back(tempCoin);
    }
    cout << endl;


    vector<vector<int>> resultOrders = placeCoins(clockSize, coins);

    cout << "max combo size: " << resultOrders.at(0).size() << endl;
    cout << "number of max combos found: " << resultOrders.size() << endl;

    cout << "press enter to end program" << endl;
    cin.get();
}

我的問題 :在進入n ^ 2循環之前,是否有存儲對象和策略可以標記所有獨特的組合,以便我可以只比較標簽而不是成員組合? * coinGroups的每個成員都有一個尾部和頭部組合被標記/索引,這樣我就不必為每個成員多次迭代組合中的所有項目。

你可以采用樹狀結構。

樹的工作方式如下:每條邊都用硬幣標記。 樹存儲的葉子引用了向量的所有成員,這些成員的尾部與從根到該離開的跟蹤相匹配。

在預處理中,您通過遍歷所有向量創建該樹並嘗試遍歷樹,如果不可能擴展樹。

在主例程中,您只需嘗試遍歷向量的每個頭部的樹。

由此得到的復雜度為O(N * M * deg),其中deg是該樹中節點的最大出度,小於不同硬幣的數量,N是向量的數量,M是大小尾部/頭部。 假設M和deg不隨較大輸入而上升,則為O(N)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM