Algorithm 最大和递增子序列,改变算法使用记忆
我有下面的代码,它实现了这个问题的递归解决方案,而不是使用引用变量“x”来存储总体最大值,我如何或者我可以从递归返回结果,这样我就不必使用有助于记忆的“x”Algorithm 最大和递增子序列,改变算法使用记忆,algorithm,recursion,memoization,Algorithm,Recursion,Memoization,我有下面的代码,它实现了这个问题的递归解决方案,而不是使用引用变量“x”来存储总体最大值,我如何或者我可以从递归返回结果,这样我就不必使用有助于记忆的“x” // Test Cases: // Input: {1, 101, 2, 3, 100, 4, 5} Output: 106 // Input: {3, 4, 5, 10} Output: 22 int sum(vector<int> seq) { int x = INT32_MIN; helper(seq
// Test Cases:
// Input: {1, 101, 2, 3, 100, 4, 5} Output: 106
// Input: {3, 4, 5, 10} Output: 22
int sum(vector<int> seq)
{
int x = INT32_MIN;
helper(seq, seq.size(), x);
return x;
}
int helper(vector<int>& seq, int n, int& x)
{
if (n == 1) return seq[0];
int maxTillNow = seq[0];
int res = INT32_MIN;
for (int i = 1; i < n; ++i)
{
res = helper(seq, i, x);
if (seq[i - 1] < seq[n - 1] && res + seq[n - 1] > maxTillNow) maxTillNow = res + seq[n - 1];
}
x = max(x, maxTillNow);
return maxTillNow;
}
//测试用例:
//输入:{1101,2,3100,4,5}输出:106
//输入:{3,4,5,10}输出:22
整数和(向量顺序)
{
int x=int 32_MIN;
助手(seq,seq.size(),x);
返回x;
}
int-helper(向量和序列、int-n、int-x)
{
如果(n==1)返回seq[0];
int maxTillNow=seq[0];
intres=INT32_MIN;
对于(int i=1;imaxTillNow)maxTillNow=res+seq[n-1];
}
x=最大值(x,最大值);
立即返回maxTillNow;
}
首先,我认为这个实现不正确。对于这个输入{5,1,2,3,4}
它给出14,而正确的结果是10
为了编写这个问题的递归解决方案,您不需要将x作为参数传递,因为x是您期望从函数本身获得的结果。相反,您可以按照以下方式构造状态:
- 当前索引:这是您在当前步骤中处理的索引
- Last take number:这是到目前为止结果子序列中包含的最后一个数字的值。这是为了确保在以下步骤中选择较大的数字,以保持结果子序列的增加
sum(当前索引,上次取数)=从当前索引到结束的最大递增和,因为您必须选择大于上次取数的元素以保持递增的子序列
,其中您想要的答案是sum(0,一个小值)
因为它计算整个序列的结果。通过一个小值
我的意思是比整个序列中的任何其他值都小
sum(当前索引、最后获取的编号)
可以使用较小的子状态递归计算。首先假设简单的情况:
- N=0,结果是0,因为根本没有序列
- N=1,序列只包含一个数字,如果数字为负,则结果为该数字或0(我将空子序列视为有效子序列,因此不取任何数字是有效答案)
- 或者忽略第一个数字,那么问题可以减少到N=1版本,其中该数字是序列中的最后一个数字。在这种情况下,结果与
相同,其中sum(1,MIN_VAL)
,因为我们已经处理了index=0并决定忽略它,而MIN_VAL是我们上面提到的小值current_index=1
- 拿第一个号码。假设its值为X,则结果为
。这意味着解决方案包括X,因为您决定将其包括在序列中,再加上X+和(1,X)
的结果。请注意,我们使用sum(1,X)
调用sum,因为我们决定取X,所以我们选择的以下值必须大于XMIN_VAL=X
sum(当前索引,最小值)=max(
求和(当前索引+1,最小值)//忽略,
seq[当前索引]+和(当前索引+1,seq[当前索引])//取
)
第二个决定并不总是有效的,因此您必须确保当前元素>MIN_VAL才能有效地执行它
这是该想法的伪代码:
sum(current_index, MIN_VAL){
if(current_index == END_OF_SEQUENCE) return 0
if( state[current_index,MIN_VAL] was calculated before ) return the perviously calculated result
decision_1 = sum(current_index + 1, MIN_VAL) // ignore case
if(sequence[current_index] > MIN_VAL) // decision_2 is valid
decision_2 = sequence[current_index] + sum(current_index + 1, sequence[current_index]) // take case
else
decision_2 = INT_MIN
result = max(decision_1, decision_2)
memorize result for the state[current_index, MIN_VAL]
return result
}
您指出的有趣的测试用例。让我重做一遍,然后回来。您的psuedo代码类似于硬币兑换或类似问题的类似解决方案,这些问题要求您选择一个值,沿着一条路径,并在回溯时彻底搜索剩余的值。它是类似的,只是您不会彻底搜索,因为记忆会切断许多不必要的探索。如果你需要更多的帮助,请告诉我。