C++ LeetCode #377 的 DP 解决方案中,此代码是否有错误?

C++ DP solution to LeetCode #377, does this code have a bug?

本文关键字:代码 是否 有错误 #377 LeetCode DP 解决方案 C++      更新时间:2023-10-16

这个C++解决方案是对论坛中投票最多的Java解决方案的直接翻译。我自己的 G++ 编译器可以很好地编译并运行它,但是 LeetCode 提交会产生错误(请快速尝试(。

我认为内存已正确初始化,边界检查已到位。可能是什么问题?

class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<int> dp(target + 1, 0);
dp[0] = 1;
for (int i = 1; i < dp.size(); i++) {
for (int j = 0; j < nums.size(); j++) {
if (i - nums[j] >= 0) {
dp[i] += dp[i - nums[j]];
}
}
}
return dp[target];
}
};
int main(int argc, char** argv) {
vector<int> nums {
3, 33, 333,
};
cout << Solution().combinationSum4(nums, 10000) << endl;
return 0;
}

测试用例:

[3,33,333]
10000

错误信息:

Line 9: Char 17: runtime error: signed integer overflow: 357856184 + 1941940377 cannot be represented in type 'int' (solution.cpp)

该消息清楚地显示了错误。 357856184 + 1941940377 = 2299796561大于 32 位 int max -> 2^31 - 1 = 2147483647。

在C++标准中,不能保证int的大小。因此,为了安全起见,您可以使用int64_t,根据C++ 11。

https://en.cppreference.com/w/cpp/language/types

这个算法是正确的,但有缺陷。它在计算过程中不处理整数溢出。改进的解决方案如下:

class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<long> dp(target + 1, 0);
dp[0] = 1;
for (int i = 1; i < dp.size(); i++) {
for (int j = 0; j < nums.size(); j++) {
if (i - nums[j] >= 0) {
dp[i] += dp[i - nums[j]];
dp[i] %= numeric_limits<int>::max();
}
}
}
return dp[target];
}
};