C++ 为什么我的leetcode 322硬币解决方案会更改超时
这是我的密码:C++ 为什么我的leetcode 322硬币解决方案会更改超时,c++,algorithm,C++,Algorithm,这是我的密码: class Solution { std::unordered_map<int, int> um; public: int coinChange(vector<int>& coins, int amount) { if (amount == 0) return 0; auto it = um.find(amount); if (it != um.end())
class Solution {
std::unordered_map<int, int> um;
public:
int coinChange(vector<int>& coins, int amount) {
if (amount == 0)
return 0;
auto it = um.find(amount);
if (it != um.end())
return it->second;
int ret = -1;
for (int c : coins)
{
int n = 1;
while (true)
{
int a = amount - n * c, m = 0;
if (a < 0)
break;
if (a > 0)
m = coinChange(coins, a);
if (m != -1)
{
if (ret == -1)
ret = m + n;
else
ret = std::min(ret, m + n);
}
n++;
}
}
um[amount] = ret;
return ret;
}
};
请原谅我对这个问题的困惑,我相信我对上述想法的实施有一些缺陷,但我很难找到它。稍后编辑:我错了 我注意到C版本的运行时间仍然太长,所以这不是问题所在。我设法从Leetcode获得了所有测试,并发现了问题 对于测试用例coins:{3,7,405,436}和amount:8839,我的实现将进行18744855次调用,而最流行的只有34486次 这是因为,对于每一枚硬币,我会尽可能多次地将其放入数量中(while(true)循环),每次尝试后,我都会进行递归调用。它是这样的(对于硬币={1}和数量=3): 但是,只需尝试一次硬币,然后让递归调用处理其余部分就足够了,就像流行的解决方案一样:
S(3) = min{1 + S(2)}
S(2) = min{1 + S(1)}
S(1) = min{1 + S(0)}
S(0) = 0
先前的答案:
我已经将相同的精确解决方案移植到了C中,并且得到了认可,因此我认为这是Leetcode基础架构中的一些问题
int coinChange_(int* coins, int coinsSize, int *um, int amount) {
if (amount == 0)
return 0;
if (um[amount] != 0)
return um[amount];
int ret = -1;
for (int i = 0; i < coinsSize; i++)
{
int c = coins[i];
int n = 1;
while (true)
{
int a = amount - n * c, m = 0;
if (a < 0)
break;
if (a > 0)
m = coinChange_(coins, coinsSize, um, a);
if (m != -1)
{
if (ret == -1)
ret = m + n;
else
ret = m + n < ret ? m + n : ret;
}
n++;
}
}
um[amount] = ret;
return ret;
}
int coinChange(int* coins, int coinsSize, int amount) {
int *um = calloc(amount + 1, sizeof *um);
int ret = coinChange_(coins, coinsSize, um, amount);
free(um);
return ret;
}
int coinChange_u2;(int*coins,int coinsize,int*um,int amount){
如果(金额=0)
返回0;
如果(um[金额]!=0)
返回um[金额];
int-ret=-1;
for(int i=0;i0)
m=货币变化(货币,货币化,嗯,a);
如果(m!=-1)
{
如果(ret==-1)
ret=m+n;
其他的
ret=m+n
a是否可以是0?看起来如果是0,你的代码将永远循环。尝试使用调试器并逐步完成代码…如果你想从事软件开发人员的职业,那么最好远离那些虚假的竞争性编程网站。他们传播有害的知识,却毫无贡献。@mame98,我这样做了,我在运行单个输入时,无论是在本地还是在web界面上,都没有发现任何问题。那些有竞争力的编程网站接受任何碰巧通过测试的垃圾程序。他们并没有真正教你如何正确地编写程序。你发现了解决方案是很好的。但是在C++版本中,你使用了无序的映射,发现元素会增加时间复杂度,如果你将代码增量移植到C++,而不是直接跳转到试图获得<代码>无序的映射>代码>工作。如果um
是一个非本地std::vector
,并且只调用resize()
来调整向量大小,您会发现您的coinChange
函数可能会运行得更快。现在,您正在调用calloc
和free
,如果多次调用coinChange
,这会增加所需的时间。@PaulMcKenzie,我知道这一点。我发现了真正的问题并更新了答案。这是算法中的一个微妙缺陷。
S(3) = min{1 + S(2)}
S(2) = min{1 + S(1)}
S(1) = min{1 + S(0)}
S(0) = 0
int coinChange_(int* coins, int coinsSize, int *um, int amount) {
if (amount == 0)
return 0;
if (um[amount] != 0)
return um[amount];
int ret = -1;
for (int i = 0; i < coinsSize; i++)
{
int c = coins[i];
int n = 1;
while (true)
{
int a = amount - n * c, m = 0;
if (a < 0)
break;
if (a > 0)
m = coinChange_(coins, coinsSize, um, a);
if (m != -1)
{
if (ret == -1)
ret = m + n;
else
ret = m + n < ret ? m + n : ret;
}
n++;
}
}
um[amount] = ret;
return ret;
}
int coinChange(int* coins, int coinsSize, int amount) {
int *um = calloc(amount + 1, sizeof *um);
int ret = coinChange_(coins, coinsSize, um, amount);
free(um);
return ret;
}