我在接受采访时被问到了这个问题,但无法弄明白并且想知道答案。
假设我们有一个这样的列表:
1 7 8 6 1 1 5 0
我需要找到一个算法,使它与相邻的数字配对。目标是最大化利益,但只计算对中的第一个数字。
例如,在上文中,最佳解决方案是:{7,8} {6,1} {5,0}
所以当只拍摄第一个时:
7 + 6 + 5 = 18.
我尝试了各种贪婪的解决方案,但他们常常选择{8,6}
,这会导致非最佳解决方案。
思想?
答案 0 :(得分:5)
首先,观察跳过多个 * 是没有意义的。然后,观察可以通过比较两个数字来构建这个问题的答案:
最后,观察到只有一个数字的序列问题的答案为零,只有两个数字的问题的解决方案是两个数字中的第一个数字。
掌握了这些信息后,您可以构建一个递归memoized问题的解决方案,或者从后面开始的动态编程解决方案,然后再决定是否包含以前的数字。
* 证明:假设您有一个产生最大总和的序列,并且它跳过原始序列中的两个数字。然后你可以添加你跳过的那对,并改进答案。
答案 1 :(得分:4)
一个简单的动态编程问题。从一个特定索引开始,我们可以 在当前索引处创建一对,或者跳过到下一个索引:
int []dp;//Array to store result of sub-problem
boolean[]check;//Check for already solve sub-problem
public int solve(int index, int []data){
if(index + 1 >= data.length){//Special case,which cannot create any pair
return 0;
}
if(check[index]){//If this sub-problem is solved before, return the value
return dp[index];
}
check[index] = true;
//Either make a pair at this index, or skip to next index
int result = max(data[index] + solve(index + 2, data) , solve(index + 1,data));
return dp[index] = result;
}
答案 2 :(得分:1)
这是一个动态编程问题,可以优化表格。
def best_pairs(xs):
b0, b1 = 0, max(0, xs[0])
for i in xrange(2, len(xs)):
b0, b1 = b1, max(b1, xs[i-1]+b0)
return b1
print best_pairs(map(int, '1 7 8 6 1 1 5 0'.split()))
在每次迭代之后,b1是使用i之前和之后的元素的最佳解决方案,而b0是使用i-1之类的元素的最佳解决方案。
答案 3 :(得分:1)
这是我在Java中的解决方案,希望它有所帮助。
public static int getBestSolution(int[] a, int offset) {
if (a.length-offset <= 1)
return 0;
if (a.length-offset == 2)
return a[offset];
return Math.max(a[offset] + getBestSolution(a,offset+2),
getBestSolution(a,offset+1));
}
答案 4 :(得分:1)
这是O(N)溶液的DP配方: -
MaxPairSum(i)= Max(arr [i] + MaxPairSum(i + 2),MaxPairSum(i + 1))
MaxPairSum(i)是子阵列(i,N)的最大总和