[英]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.