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