【问题标题】:Maximum Score from Performing Multiplication Operations执行乘法运算的最高分数
【发布时间】:2025-12-08 21:40:01
【问题描述】:

给定两个整数数组 nums 和大小分别为 n 和 m 的乘数,其中 n >= m。数组是 1 索引的。

你从 0 分开始。你想执行 m 个操作。在第 i 个操作(1-indexed)上,您将:

约束: 1.从数组nums的开头或结尾选择一个整数x。

2.将乘数[i] * x 添加到您的分数中。

3.从数组nums中删除x。

执行m次操作后返回最高分。

例如:nums = [-5,-3,-3,-2,7,1] 和乘数 = [-10,-5,3,4,6]

输出:102

public int maximumScore(int[] nums, int[] multipliers) {
    int totalValue = 0;
    int length = multipliers.length;
    int start = 0;
    for(int i =0,j=nums.length-1;i<=j && length!=0;){
        int max = 0;
        if(nums[i] * multipliers[start] > nums[j]*multipliers[start]){
            max = nums[i] * multipliers[start];
            i++;
        }else{
            max = nums[j]*multipliers[start];
            j--;
        }
        start++;
        totalValue+=max;
        
        length--;
    }
    
    return totalValue;
}

我的代码,但遗憾的是不起作用并将输出打印为 120 .. 任何带有解释的解决方案都会有所帮助,谢谢。

【问题讨论】:

  • 您的示例输入有问题,因为我的结果是 84,而不是 120
  • @aran 数字看起来不错。 解决方案: -10 * -5(start) + -5 * -3(start) + 3 * -3(start) + 4 * 1(end) + 6 * 7(end) = 102
  • @Andreas nope,看jdoodle.com/iembed/v0/9F9 - 甚至短路了其中一个数组,但值是 78 和 84,具体取决于该排序
  • @aran 哦,你说的是问题代码的实际输出,而不是问题的正确解决方案。我误解了你的评论,对不起。
  • @Andreas nono,我没有猜到这是结果,只是具有给定值的示例的输出。干杯! 而且你总是得到它男孩..

标签: java arrays multiplication


【解决方案1】:

判断是从nums的开头还是结尾取下一个值的逻辑不正确。

您的代码匹配这样的数字:

 -5    -3    -3    -2     7     1    nums
  │     │     ┌─────┼─────┼─────┘
  │     │     │     │  ┌──┘
  │     │     │     └──┼──┐
  │     │     │     ┌──┘  │
-10    -5     3     4     6         multipliers
  =     =     =     =     =
 50 +  15 +   3 +  28 + -12 =  84

这是因为,在第 3 次迭代中,逻辑比较 -3(start) * 3 = -91(end) * 3 = 3,并从末尾选择值,因为 3 &gt; -9

但是,如果在第 3 次迭代而不是在第 5 次迭代中取负值的成本,结果会更高。

 -5    -3    -3    -2     7     1    nums
  │     │     │           │     │
  │     │     │     ┌─────┼─────┘
  │     │     │     │     │
-10    -5     3     4     6         multipliers
  =     =     =     =     =
 50 +  15 +  -9 +   4 +  42 = 102

不知道是否有比蛮力更好的方法,但它会找到正确的解决方案。

static void solve(int[] nums, int[] multipliers) {
    if (multipliers.length > 30)
        throw new IllegalArgumentException("Too many multipliers (max 30): " + multipliers.length);
    final int end = 1 << multipliers.length;
    int maxSum = Integer.MIN_VALUE, maxBits = 0;
    for (int bits = 0; bits < end; bits++) {
        int sum = calc(nums, multipliers, bits, null);
        if (sum > maxSum) {
            maxSum = sum;
            maxBits = bits;
        }
    }
    StringBuilder expr = new StringBuilder();
    calc(nums, multipliers, maxBits, expr);
    System.out.println(expr);
}

private static int calc(int[] nums, int[] multipliers, int bits, StringBuilder expr) {
    int sum = 0, idx0 = 0, idx1 = nums.length;
    for (int i = 0; i < multipliers.length; i++) {
        boolean fromStart = ((bits & (1 << i)) == 0);
        int num = (fromStart ? nums[idx0++] : nums[--idx1]);
        sum += multipliers[i] * num;
        if (expr != null) {
            if (i != 0)
                expr.append(" + ");
            expr.append(multipliers[i]).append(" * ").append(num).append(fromStart ? "(start)" : "(end)");
        }
    }
    if (expr != null)
        expr.append(" = ").append(sum);
    return sum;
}

测试

solve(new int[] {-5,-3,-3,-2,7,1}, new int[] {-10,-5,3,4,6});

输出

-10 * -5(start) + -5 * -3(start) + 3 * -3(start) + 4 * 1(end) + 6 * 7(end) = 102

当然,如果没有用于打印表达式的所有额外代码,代码会小得多:

static int solve(int[] nums, int[] multipliers) {
    if (multipliers.length > 30)
        throw new IllegalArgumentException("Too many multipliers (max 30): " + multipliers.length);
    final int end = 1 << multipliers.length;
    int maxSum = Integer.MIN_VALUE;
    for (int bits = 0; bits < end; bits++) {
        int sum = 0, idx0 = 0, idx1 = nums.length;
        for (int i = 0; i < multipliers.length; i++)
            sum += multipliers[i] * ((bits & (1 << i)) == 0 ? nums[idx0++] : nums[--idx1]);
        maxSum = Math.max(maxSum, sum);
    }
    return maxSum;
}

这种蛮力方法的性能是O(2m)

【讨论】:

    【解决方案2】:

    可以使用递归解决问题,然后使用动态规划针对重叠子问题进行优化。一个简单的递归解决方案如下所示(在 C++ 中):

    int solver(int i, vector<int>& n, vector<int>& m, int s, int e) {
        if(i == size(m)) return 0;
        return max(m[i] * n[s] + solver(i + 1, n, m, s + 1, e), m[i] * n[e] + solver(i + 1, n, m, s, e - 1));
        return dp[i][s];
      }
    
    int maximumScore(vector<int>& nums, vector<int>& multipliers) {
        int score = solver(0, nums, multipliers, 0, nums.size() - 1);
        return score;
    }
    

    这可以通过将结果存储在一个数组中并使用它们而不是再次计算相同的问题来进一步优化。

    class Solution {
    public:
        int dp[1001][1001];
        int solver(int i, vector<int>& n, vector<int>& m, int s) {
            if(i == size(m)) return 0;
            int e = n.size() - 1 - (i - s);
            if(dp[i][s] == -1) 
                dp[i][s] = max(m[i] * n[s] + solver(i + 1, n, m, s + 1), m[i] * n[e] + solver(i + 1, n, m, s));
            return dp[i][s];
        }
        
        int maximumScore(vector<int>& nums, vector<int>& multipliers) {
            memset(dp, -1, sizeof dp);
            int score = solver(0, nums, multipliers, 0);
            return score;
        }
    };
    

    【讨论】: