繁体   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