找到最佳相邻对,以便最大化第一个元素的总和

时间:2014-01-19 21:02:28

标签: algorithm

我在接受采访时被问到了这个问题,但无法弄明白并且想知道答案。

假设我们有一个这样的列表:

1 7 8 6 1 1 5 0

我需要找到一个算法,使它与相邻的数字配对。目标是最大化利益,但只计算对中的第一个数字。

例如,在上文中,最佳解决方案是:

{7,8} {6,1} {5,0}

所以当只拍摄第一个时:

7 + 6 + 5 = 18.

我尝试了各种贪婪的解决方案,但他们常常选择{8,6},这会导致非最佳解决方案。

思想?

5 个答案:

答案 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)的最大总和