Javascript 尝试在不使用其他算法的情况下使用递归求解
我试图更好地理解递归,以便更好地实现动态编程原理。我知道这个问题可以用Kadane的算法解决;但是,我想使用递归来解决它 问题陈述: 给定一个整数数组,找到具有最大和的非相邻元素的子集。计算该子集的和 我编写了以下部分解决方案:Javascript 尝试在不使用其他算法的情况下使用递归求解,javascript,algorithm,recursion,Javascript,Algorithm,Recursion,我试图更好地理解递归,以便更好地实现动态编程原理。我知道这个问题可以用Kadane的算法解决;但是,我想使用递归来解决它 问题陈述: 给定一个整数数组,找到具有最大和的非相邻元素的子集。计算该子集的和 我编写了以下部分解决方案: const maxSubsetSum = (arr) => { let max = -Infinity const helper = (arr, len) => { if (len < 0) return max
const maxSubsetSum = (arr) => {
let max = -Infinity
const helper = (arr, len) => {
if (len < 0) return max
let pointer = len
let sum = 0
while (pointer >= 0) {
sum += arr[pointer]
pointer -= 2
}
return max = Math.max(sum, helper(arr, len - 1))
}
return helper(arr, arr.length - 1)
}
我的算法计算13。我知道这是因为当我开始我的算法时,我的(n-2)值是计算出来的,但我没有考虑其他(n-3)或更多的子集,它们仍然验证问题陈述的条件。我无法理解解释其他值的逻辑,请指导我如何实现。代码将递归(调用
helper
insidehelper
)与迭代(调用while
循环insidehelper
)相结合。您应该只使用递归
对于数组的每个元素,有两种选择:
sum1=helper(arr,len-1,sum)
sum2=helper(arr,len-2,sum+arr[len])
const maxSubsetSum = (arr) => {
const helper = (arr, len, sum) => {
if (len < 0) return sum
let sum1 = helper(arr, len - 1, sum)
let sum2 = helper(arr, len - 2, sum + arr[len])
return Math.max(sum1, sum2)
}
return helper(arr, arr.length - 1, 0)
}
const maxSubsetSum=(arr)=>{
常量助手=(arr、len、sum)=>{
如果(len<0)返回和
设sum1=helper(arr,len-1,sum)
设sum2=helper(arr,len-2,sum+arr[len])
返回Math.max(sum1,sum2)
}
返回帮助器(arr,arr.length-1,0)
}
您的想法是正确的,一旦您从当前索引开始,就需要从(n-2)递归。但您似乎不明白,您不需要运行数组来获得和,然后递归。
所以正确的方法是
- 包括当前项并在剩余的n-2项上递归,或
- 不包括当前项并在剩余的n-1项上递归
const maxSubsetSum = (arr) => {
let min = -Infinity
const helper = (arr, idx) => {
if ( idx < 0 ) return min
let inc = helper(arr, idx-2)
let notInc = helper(arr, idx-1)
inc = inc == min ? arr[idx] : Math.max(arr[idx], arr[idx] + inc)
return Math.max( inc, notInc )
}
return helper(arr, arr.length - 1)
}
console.log(maxSubsetSum([-3, -5, -7, -8, 10]))
console.log(maxSubsetSum([-3, -5, -7, -8, -10]))
console.log(maxSubsetSum([-3, 5, 7, -8, 10]))
console.log(maxSubsetSum([3, 5, 7, 8, 10]))
- 对于所有项目均为负值的情况:
const maxSubsetSum = (arr) => {
const helper = (arr, idx) => {
if ( idx < 0 ) return 0
let inc = arr[idx] + helper(arr, idx-2)
let notInc = helper(arr, idx-1)
return Math.max( inc, notInc )
}
return helper(arr, arr.length - 1)
}
const maxSubsetSum=(arr)=>{
const helper=(arr,idx)=>{
如果(idx<0)返回0
let inc=arr[idx]+助手(arr,idx-2)
let notInc=helper(arr,idx-1)
return Math.max(inc,notInc)
}
返回帮助器(arr,arr.length-1)
}
- 随附备忘录:
const maxSubsetSum = (arr) => {
let min = -Infinity
let memo = new Array(arr.length).fill(min)
const helper = (arr, idx) => {
if ( idx < 0 ) return min
if ( memo[idx] !== min) return memo[idx]
let inc = helper(arr, idx-2)
let notInc = helper(arr, idx-1)
inc = inc == min ? arr[idx] : Math.max(arr[idx], arr[idx] + inc)
memo[idx] = Math.max( inc, notInc )
return memo[idx]
}
return helper(arr, arr.length - 1)
}
const maxSubsetSum=(arr)=>{
设min=-无穷大
let memo=新数组(arr.length).fill(min)
const helper=(arr,idx)=>{
如果(idx<0)返回最小值
如果(备忘录[idx]!==min)返回备忘录[idx]
let inc=helper(arr,idx-2)
let notInc=helper(arr,idx-1)
inc=inc==min?arr[idx]:数学最大值(arr[idx],arr[idx]+inc)
备注[idx]=Math.max(inc,notInc)
返回备忘录[idx]
}
返回帮助器(arr,arr.length-1)
}
基本版本非常简单,具有明显的递归。我们要么在总和中包含当前值,要么不包含当前值。如果我们这样做,我们需要跳过下一个值,然后在剩余的值上重复。如果没有,则需要在当前值之后的所有值上重复出现。我们选择这两个结果中较大的一个。这几乎直接转化为代码:
const maxSubsetSum = ([n, ...ns]) =>
n == undefined // empty array
? 0
: Math .max (n + maxSubsetSum (ns .slice (1)), maxSubsetSum (ns))
此代码已被接受:
函数maxSubsetSum(A){
返回A.reduce((ux,i)=>
A[i]=Math.max(A[i],A[i-1]|0,A[i]+(A[i-2]|0));
}
但是,如果尝试递归那么远,(我尝试提交Scott Sauyet的),我相信会导致运行时错误,因为我们可能会超过递归限制
为了好玩,这里有一个自下而上的自上而下的方法:)
函数f(A,i=0){
如果(i>A.length-3)
返回A[i]=Math.max(A[i]| 0,A[i+1]|0);
//填表
f(A,i+1);
返回A[i]=Math.max(A[i],A[i]+A[i+2],A[i+1]);
}
变量As=[
[3, 7, 4, 6, 5], // 13
[2, 1, 5, 8, 4], // 11
[3, 5, -7, 8, 10] // 15
];
例如{
控制台日志(“”+A);
控制台日志(f(A));
}
这很有帮助,您将如何记忆此解决方案?它是2D数组还是1D数组?@Altaf我认为它是1D数组,因为唯一需要记忆的是给定len
的部分和。我在记忆解决方案时遇到困难,所以我所做的是在helperconst newArr=new array(arr.length)之前声明一个数组。fill(-1)
编写了一个条件以返回if(newArr[len]!==-1)返回newArr[len]
然后将helper函数的返回值更改为返回newArr[len]=Math.max(sum1,sum2)
,但是我没有做正确的事情。这为输入[-3]提供了0
const maxSubsetSum = (arr) => {
let min = -Infinity
let memo = new Array(arr.length).fill(min)
const helper = (arr, idx) => {
if ( idx < 0 ) return min
if ( memo[idx] !== min) return memo[idx]
let inc = helper(arr, idx-2)
let notInc = helper(arr, idx-1)
inc = inc == min ? arr[idx] : Math.max(arr[idx], arr[idx] + inc)
memo[idx] = Math.max( inc, notInc )
return memo[idx]
}
return helper(arr, arr.length - 1)
}
const maxSubsetSum = ([n, ...ns]) =>
n == undefined // empty array
? 0
: Math .max (n + maxSubsetSum (ns .slice (1)), maxSubsetSum (ns))