The logic deciding whether to take the next value from the start or end of nums
is incorrect.
Your code matches up numbers like this:
-5 -3 -3 -2 7 1 nums
│ │ ┌─────┼─────┼─────┘
│ │ │ │ ┌──┘
│ │ │ └──┼──┐
│ │ │ ┌──┘ │
-10 -5 3 4 6 multipliers
= = = = =
50 + 15 + 3 + 28 + -12 = 84
That is because, on the 3rd iteration, the logic compares -3(start) * 3 = -9
vs 1(end) * 3 = 3
, and chooses the value from the end, since 3 > -9
.
However, if you take the cost of the negative value on the 3rd iteration, instead of on the 5th iteration, the result is higher.
-5 -3 -3 -2 7 1 nums
│ │ │ │ │
│ │ │ ┌─────┼─────┘
│ │ │ │ │
-10 -5 3 4 6 multipliers
= = = = =
50 + 15 + -9 + 4 + 42 = 102
Don't know if there's a better way than brute-force, but it will find the correct solution.
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;
}
Test
solve(new int[] {-5,-3,-3,-2,7,1}, new int[] {-10,-5,3,4,6});
Output
-10 * -5(start) + -5 * -3(start) + 3 * -3(start) + 4 * 1(end) + 6 * 7(end) = 102
Of course, without all that extra code for printing the expression, the code is much smaller:
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;
}
The performance of this brute-force approach is O(2m)