【发布时间】:2018-06-21 12:08:43
【问题描述】:
我有一个低效的递归硬币找零函数,它计算出给定数量的硬币组合数量。如果可能,我想将其转换为更高效的迭代函数。
一个问题是我正在使用回溯来尝试一个称为面额的数组中的不同硬币。我也在使用 memoization,但是当数量很大时它不会加快速度。
这是我的代码:
unsigned long long CalculateCombinations(std::vector<double> &denominations, std::vector<double> change,
double amount, unsigned int index)
{
double current = 0.0;
unsigned long long combinations = 0;
if (amount == 0.0)
{
if (change.size() % 2 == 0)
{
combinations = Calculate(change);
}
return combinations;
}
// If amount is less than 0 then no solution exists
if (amount < 0.0)
return 0;
// If there are no coins and index is greater than 0, then no solution exist
if (index >= denominations.size())
return 0;
std::string str = std::to_string(amount) + "-" + std::to_string(index) + "-" + std::to_string(change.size());
auto it = Memo.find(str);
if (it != Memo.end())
{
return it->second;
}
while (current <= amount)
{
double remainder = amount - current;
combinations += CalculateCombinations(denominations, change, remainder, index + 1);
current += denominations[index];
change.push_back(denominations[index]);
}
Memo[str] = combinations;
return combinations;
}
任何想法如何做到这一点?我知道硬币找零问题有 DP 解决方案,但我的解决方案并不容易解决。我可以有半便士。
*更新:我将函数更改为迭代,并按 2 倍放大以使用整数,但没有太大区别。
这是我的新代码:
unsigned long long CalculateCombinations(std::vector<int> &denominations, std::vector<int> change, int amount, unsigned int index)
{
unsigned long long combinations = 0;
if (amount <= 0)
return combinations;
std::stack<Param> mystack;
mystack.push({ change, amount, index });
while (!mystack.empty())
{
int current = 0;
std::vector<int> current_coins = mystack.top().Coins;
int current_amount = mystack.top().Amount;
unsigned int current_index = mystack.top().Index;
mystack.pop();
if (current_amount == 0)
{
if (current_coins.size() % 2 == 0)
{
combinations += Calculate(std::move(current_coins));
}
}
else
{
std::string str = std::to_string(current_amount) + "-" + std::to_string(current_index);
if (Memo.find(str) == Memo.end())
{
// If amount is less than 0 then no solution exists
if (current_amount >= 0 && current_index < denominations.size())
{
while (current <= current_amount)
{
int remainder = current_amount - current;
mystack.push({ current_coins, remainder, current_index + 1 });
current += denominations[current_index];
current_coins.push_back(denominations[current_index]);
}
}
else
{
Memo.insert(str);
}
}
}
}
return combinations;
}
Memo 被定义为 std::unordered_set。
DP能解决这个问题吗?问题是我对所有组合都不感兴趣——只对大小均匀的组合感兴趣。
【问题讨论】:
-
如果算法保持不变,即使它是迭代的,是否会改变效率?
-
您能否详细说明您的“效率”概念?您认为递归方法在哪些方面效率低下?
-
我认为您效率低下的原因可能是您通过跟踪分发的硬币并进行大量内存分配使事情变得复杂。
-
您可以通过使用整数而不是浮点数来提高程序的效率。尽管某些浮点处理器可能与整数运算一样快(或更快)。
-
Memo在哪里定义?我收到编译错误。
标签: c++ recursion coin-change