给定n个非负整数的数组(arr []),我们必须找到元素的最小总和,以便挑选每3个连续元素中的至少一个元素。
Input : arr[] = {1, 2, 3}
Output : 1
Input : arr[] = {1, 2, 3, 6, 7, 1}
Output : 4
We pick 3 and 1 (3 + 1 = 4)
Note that there are following subarrays
of three consecutive elements
{1, 2, 3}, {2, 3, 6}, {3, 6, 7} and {6, 7, 1}
We have picked one element from every subarray.
Input : arr[] = {1, 2, 3, 6, 7, 1, 8, 6, 2,
7, 7, 1}
Output : 7
The result is obtained as sum of 3 + 1 + 2 + 1
这个的递归方程如下:
sum[i]= arr[i] + min(sum[i-1],sum[i-2],sum[i-3])
where the base condition is:
if i==3, then sum(3)= arr[3] + min(sum(0),sum(1),sum(2)) where
sum(0)=arr[0]
sum(1)=arr[1]
sum(2)=arr[2]
result=min(sum(n-1), sum(n-2), sum(n-3))
请解释形成的递归方程背后的直觉。为什么添加当前的i th 数组元素和最后三次递归调用的结果的min给出了大小为i的数组的正确答案?
答案 0 :(得分:2)
递归公式确实是正确的,但只有在扩展时具有以下内容:
output = min(sum(n-1), sum(n-2), sum(n-3))
...其中 n 的大小为arr
。在n < 3
的情况下,当然输出是所有arr
值中的最小值。
递归公式满足要求&#34;每3个连续元素中至少有一个元素被选中&#34; ,这与索引距离<两个相邻选择(或数组末尾)之间的/ em>最多为3:
对于 i &gt; = 3,sum(i)
将包含 i 的值,以及中的至少一个值i-1 , i-2 或 i-3 ,因为每个的sum
定义也包括该索引处的值。显然,指数差异最多为i - (i-3)
,即3。
i &lt; 3,确实如此,因为它们之前的值少于3个。
递归公式(包括最终输出的必要公式)也满足&#34;输出元素&#34; 的最小总和的要求。这是因为最佳解决方案必须包含索引 n-1 , n-2 或 n-3 ,否则不符合其他条件。
sum(i)
在必须包含 i 时最小化总和,因此sum(n-1), sum(n-2), sum(n-3)
中的最小值将找到最佳解决方案。答案 1 :(得分:0)
基于我与@trincot的对话。我对为什么有一个函数sum()
和列表sum[]
感到有点困惑。我做了一点搜索,我认为这是因为解决方案涉及使用动态编程生成列表sum
并使用它将答案存储为sum[i]
如果我们使用输入的第一个i项阵列。
如果您阅读了trincot的答案并感到困惑,并想知道代码看起来如下所示(在Java中):
import java.lang.Math;
import java.util.Arrays;
public class MinSumThreeConsec{
public static int minSumThreeConsec(int[] arr){
int n = arr.length;
if(n == 0){
return 0;
}
//if the length of the array lenght is 3 or less
if(n <= 3){
Arrays.sort(arr);
return arr[0];
}
//if array size is larger than 3 than we need to use DP to pupulate the list sum
int[] sum = new int[n];
//fill out the base cases
sum[0] = arr[0];
sum[1] = arr[1];
sum[2] = arr[2];
for(int i = 3; i<n; i++){
sum[i] = arr[i] + min(sum[i-1], sum[i-2], sum[i-3]); //include value at index i in arr. and the mimum value from sum[i-1], sum[i-2], sum[i-3]
}
return min(sum[n-1], sum[n-2], sum[n-3]); //refer to trincot's answer above
}
public static int min(final int a, final int b, final int c){
return Math.min(a, Math.min(b, c));
}
public static void main(String[] args){
int[] arr = {};
System.out.print(minSumThreeConsec(arr)); //empty case print 0
int[] arr1 = {3,2,1};
System.out.print(minSumThreeConsec(arr1)); //print 1
int[] arr2 = {1, 2, 3, 6, 7, 1};
System.out.print(minSumThreeConsec(arr2)); //print 4
int[] arr3 = {1, 2, 3, 6, 7, 1, 8, 6, 2, 7, 7, 1}; //print 7
System.out.print(minSumThreeConsec(arr3));
int[] arr4 = {1, 2, 3, 6, 7, 1, -8, 6, 2, 7, 7, 1}; //print -1
System.out.print(minSumThreeConsec(arr4));
}
}
我认为这甚至适用于列表中的负数。