C++ 递归函数工作,但无法记忆
我正在LeetCode.com上解决这个动态规划问题: 给您一个非负整数列表,a1、a2、…、an和目标S。现在您有2个符号+和-。对于每个整数,您应该从+和-中选择一个作为其新符号。了解分配符号使整数和等于目标S的方法。 对于输入C++ 递归函数工作,但无法记忆,c++,algorithm,recursion,dynamic-programming,memoization,C++,Algorithm,Recursion,Dynamic Programming,Memoization,我正在LeetCode.com上解决这个动态规划问题: 给您一个非负整数列表,a1、a2、…、an和目标S。现在您有2个符号+和-。对于每个整数,您应该从+和-中选择一个作为其新符号。了解分配符号使整数和等于目标S的方法。 对于输入[1,1,1,1,1]和S=3,输出应为5 制约因素包括: 给定数组的长度为正,不会超过20 给定数组中的元素之和将不超过1000 您的输出答案保证适合32位整数。 我想出了以下代码: 类解决方案{ 公众: 向量n; int-s; int-helper(向量和dp、i
[1,1,1,1,1]
和S=3
,输出应为5
制约因素包括:
给定数组的长度为正,不会超过20给定数组中的元素之和将不超过1000
您的输出答案保证适合32位整数。
我想出了以下代码:
类解决方案{
公众:
向量n;
int-s;
int-helper(向量和dp、int-sum、int-startIndex){
如果(startIndex==n.size()){
如果(sum==s)返回dp[startIndex][sum]=1;
否则返回dp[startIndex][sum]=0;
}
如果(dp[startIndex][sum]!=-1)返回dp[startIndex][sum];
返回dp[startIndex][sum]=helper(dp,sum+n[startIndex],startIndex+1)+
助手(dp,sum-n[startIndex],startIndex+1);
}
int findTargetSumWays(向量和nums,int S){
n=nums;
s=s;
载体dp(21,载体(1001,-1));
返回帮助器(dp,0,0);
}
};
如果不使用dp
表进行记忆,代码在所有139个测试用例上都可以正常运行(139/139测试用例通过,但时间太长。
),但明显超过了时间限制。现在,在如上所述的记忆中,我得到了一个运行时错误:
运行时错误:向0x6201000008D00添加无符号偏移量溢出到0x6201000008CFC(stl_vector.h)
摘要:UndefinedBehaviorSanitizer:undefined behavior/usr/bin/./lib/gcc/x86_64-linux-gnu/8/../../../../../../include/c++/8/bits/stl_vector.h:933:34
我做错了什么?可以使用动态规划优化问题,将
当前索引
和总和
作为状态
您的解决方案的问题是,Sum
本身可能是一个非常大的数字或负数,访问如此大的索引会导致运行时错误,因为在此类平台(沙盒环境)上提供的内存有限。最好的方法是使用地图。
检查以下已接受Leetcode判断的解决方案:
typedef long long int LL;
class Solution {
public:
std::map<pair<LL, LL>, LL> mp;
LL find(int currentIndex, int len, LL S, std::vector<int>& nums){
if(mp.find(make_pair(currentIndex, S)) != mp.end()){
return mp[make_pair(currentIndex, S)];
}
if(S!=0 and currentIndex >= len){
return 0;
}
if(S==0 && currentIndex==len){
return 1;
}
LL ans = find(currentIndex+1, len, S-nums[currentIndex], nums) + find(currentIndex+1, len, S+nums[currentIndex], nums);
mp[make_pair(currentIndex, S)] = ans;
return mp[make_pair(currentIndex, S)];
}
int findTargetSumWays(vector<int>& nums, int S) {
return find(0, nums.size(), S, nums);
}
};
typedef long long int LL;
类解决方案{
公众:
std::map-mp;
LL find(int currentIndex、int len、LL S、std::vector和nums){
if(mp.find(make_pair(currentIndex,S))!=mp.end(){
返回mp[make_pair(currentIndex,S)];
}
如果(S!=0且currentIndex>=len){
返回0;
}
如果(S==0&¤tIndex==len){
返回1;
}
LL ans=find(currentIndex+1,len,S-nums[currentIndex],nums)+find(currentIndex+1,len,S+nums[currentIndex],nums);
mp[配对(当前索引,S)]=ans;
返回mp[make_pair(currentIndex,S)];
}
int findTargetSumWays(向量和nums,int S){
返回find(0,nums.size(),S,nums);
}
};
与动态编程类似,可能更清晰、更容易理解:
#include <vector>
#include <numeric>
class Solution {
public:
inline int findTargetSumWays(const std::vector<int> &nums, const int target) {
int copy_target = target;
std::vector<int> copy_nums = nums;
int sum = std::accumulate(copy_nums.begin(), copy_nums.end(), 0);
if (sum < copy_target || (sum + copy_target) & 1) {
return 0;
}
return get_subarray_sum(copy_nums, (sum + copy_target) >> 1);
}
private:
static inline int get_subarray_sum(const std::vector<int> &nums, const int target) {
std::vector<int> symbols_assign(target + 1, 0);
symbols_assign[0] = 1;
for (int num : nums)
for (int index = target; index > num - 1; index--) {
symbols_assign[index] += symbols_assign[index - num];
}
return symbols_assign[target];
}
};
#包括
#包括
类解决方案{
公众:
内联int findTargetSumWays(const std::vector&nums,const int target){
int copy_target=目标;
标准::向量拷贝_nums=nums;
int sum=std::累加(copy_nums.begin(),copy_nums.end(),0);
if(sum>1);
}
私人:
静态内联int get_subarray_sum(const std::vector&nums,const int target){
std::向量符号分配(目标+1,0);
符号分配[0]=1;
for(int-num:nums)
对于(int index=target;index>num-1;index--){
符号分配[index]+=符号分配[index-num];
}
返回符号_分配[目标];
}
};
工具书类
- 有关其他详细信息,请参见。这里有很多公认的解决方案,有各种解释和解释,有高效的算法,还有渐近/复杂性分析
1000
,这会有所帮助。啊,说得好。错过了。你能详细说明一下,为了索引的目的,将总和移动1000会有帮助吗?好的,你的总和的值可以在[-10001000]范围内。通过向其添加1000,您将拥有范围[0,2000],可用于索引。@J.Doe对向量的at()
进行一些调用,而不是使用[]
将向您显示代码出现问题的位置。通常,如果您编写了一个不带数组或指针的向量
唯一解决方案,那么这样的运行时错误几乎总是表示访问超出了范围。然后重写代码,使用at()
查看越界发生的位置。然后,您将得到一个更容易诊断的std::out\u of_range
异常,而不是运行时错误。明白了!谢谢,德米特里!如果你能把你的评论变成一个答案,我很乐意接受。