我如何正确记忆这种复发关系?
我正在解决一个问题:
给定整数列表
nums
,编写一个返回最大非贴上数字总和的函数。数字可以为0
或负面。对于nums = [5,1,1,5]
,输出应为10
。
我已经实现的动态编程逻辑如下:
vector<pair<int,int>> dp;
int helper(vector<int>& nums, int i, bool include) {
if(i>=nums.size()) return 0;
pair<int,int> p=dp[i];
if(p.first!=INT_MIN) return p.second;
int maxval=0;
if(include) maxval=nums[i]+helper(nums,i+1,false);
maxval=max(maxval,helper(nums,i+1,true));
dp[i]=make_pair(include,maxval);
return maxval;
}
int solve(vector<int>& nums) {
dp.clear();
dp.resize(nums.size(),make_pair(INT_MIN,INT_MIN));
// For all -ve numbers in input, just return `0`, as required.
int ans=max({helper(nums,0,true),helper(nums,0,false),0});
//for(auto& p: dp) {
// cout<<p.first<<" "<<p.second<<"\n";
//}
return ans;
}
当我不进行任何记忆时,我会得到正确的答案(所以我认为我的复发关系是正确的);但是,在像上述记忆时,我得了错误的答案。
我正在用于记忆的逻辑:对于i
th值,请在dp [i中存储a
,其中对的第一个值代表布尔值pair&lt&lt&lt&lt&gt;
]includ
,而对的第二个值表示结果maxvalue
针对i的当前值计算
和包括
。请注意,我对bool
使用int
,因为我需要三个值:true
,false
and“不尚未计算”。
我的回忆步骤中缺少什么?有什么更好的方法可以记住它吗?
谢谢。
I am solving a problem:
Given a list of integers
nums
, write a function that returns the largest sum of non-adjacent numbers. Numbers can be0
or negative. Fornums = [5, 1, 1, 5]
, output should be10
.
The dynamic programming logic that I have implemented is as below:
vector<pair<int,int>> dp;
int helper(vector<int>& nums, int i, bool include) {
if(i>=nums.size()) return 0;
pair<int,int> p=dp[i];
if(p.first!=INT_MIN) return p.second;
int maxval=0;
if(include) maxval=nums[i]+helper(nums,i+1,false);
maxval=max(maxval,helper(nums,i+1,true));
dp[i]=make_pair(include,maxval);
return maxval;
}
int solve(vector<int>& nums) {
dp.clear();
dp.resize(nums.size(),make_pair(INT_MIN,INT_MIN));
// For all -ve numbers in input, just return `0`, as required.
int ans=max({helper(nums,0,true),helper(nums,0,false),0});
//for(auto& p: dp) {
// cout<<p.first<<" "<<p.second<<"\n";
//}
return ans;
}
I get right answers when I don't do any memoization (so I think my recurrence relation is correct); but on memoizing it as above, I get wrong answers.
Logic that I am using for memoization: For the i
th value, store a pair<int,int>
in dp[i]
, where the first value of pair represents the boolean value include
while the second value of pair represents the result maxvalue
calculated for current value of i
and include
. Note that I use an int
for a bool
, since I need three values: true
, false
and "not yet calculated".
What am I missing in my memoization step? Any better way in which I could memoize it?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不要过度思考。记忆函数
f(p){...返回expr; }
,其中p是参数的元组,总是相同的。添加来自元组P的外部(不是递归函数的局部)映射m以返回值。然后重写f,因为在您的函数中看起来,
nums
永远不会更改。因此,您可以从P中省略P。密钥元组具有类型&lt; int,bool&gt;
,并且地图返回int
。那就是map&lt; tuple&lt; int,bool&gt;,int&gt;
。如果映射键最终是一个自然数字,并且可能的范围很小,则可以用初始化的阵列替换备忘录图,该数组以某种值表示“无值”。然后,“包含密钥”测试将成为一个检查m [p]是否与“无值”不同的东西。在实际问题中,这并不经常发生。
我会让您算出其余的,因为看来您正在学习。注意是,在适当的实现中,您不会使地图成为全局变量。您将递归方法包装在类中,并制作
nums
和备忘录两个字段,因此不需要将它们作为参数传递。Don't overthink it. Memoizing a function
f(P) { ... return Expr; }
where P is a tuple of parameters is always the same. Add an outer (not local to the recursive function) map M from tuples P to return values. Then rewrite f asIt looks like in your function,
nums
never changes. So you can get away with omitting it from P. If the remaining parameters are anint
and abool
, and the function returnsint
, then key tuples have type<int, bool>
, and the map returnsint
. That ismap<tuple<int, bool>, int>
.If the map key ends up being a natural number, and the possible range is small, then you can replace the memo map with an array initialized with some value that means "no value." Then the "contains key" test becomes a check whether M[P] is something different from "no value." In practical problems, this doesn't often happen.
I'll let you work out the rest, since it seems you're learning. A note is that in a proper implementation you wouldn't make the map a global variable. You'd wrap the recursive method in a class and make
nums
and the memo cache both fields so they don't need to be passed as parameters.扫描阵列,记录三个最大数字及其位置。如果较大的两个不相邻,则它们的总和就是答案。如果较大的两个相邻,则(#1 +#3)或(#2 +#3)将是答案,具体取决于更大的。
Scan through the array, recording the three largest numbers and their positions. If the larger two are not adjacent, then their sum is the answer. If the larger two are adjacent then either (#1 + #3) or (#2 + #3) will be the answer, depending on which is larger.