拼接数组的最大分数
难度:
标签:
题目描述
代码结果
运行时间: 71 ms, 内存: 30.8 MB
/*
* Problem: Given two integer arrays nums1 and nums2, both of length n, you can choose two integers left and right such that 0 <= left <= right < n and swap the subarrays nums1[left...right] and nums2[left...right].
* You can perform this operation once or not at all. The score of the arrays is the maximum value of sum(nums1) and sum(nums2).
* Return the maximum possible score.
*/
import java.util.stream.IntStream;
public class MaxScoreAfterSwapStream {
public static int maxScoreAfterSwap(int[] nums1, int[] nums2) {
int sum1 = IntStream.of(nums1).sum();
int sum2 = IntStream.of(nums2).sum();
int maxScore = Math.max(sum1, sum2);
int diff1 = 0, diff2 = 0;
for (int i = 0; i < nums1.length; i++) {
diff1 += nums2[i] - nums1[i];
diff2 += nums1[i] - nums2[i];
maxScore = Math.max(maxScore, Math.max(sum1 + diff1, sum2 + diff2));
if (diff1 < 0) diff1 = 0;
if (diff2 < 0) diff2 = 0;
}
return maxScore;
}
public static void main(String[] args) {
int[] nums1 = {20, 40, 20, 70, 30};
int[] nums2 = {50, 20, 50, 40, 20};
System.out.println(maxScoreAfterSwap(nums1, nums2)); // Output: 220
}
}
解释
方法:
本题解使用了贪心算法与Kadane算法(最大子数组和)的思想。首先,可以观察到交换子数组后,nums1与nums2的总和不变,变化的只是两者的分配。因此,问题转化为找到一段区间(子数组),使得在交换后,两个数组中的最大总和最大。对于任何一对位置i,交换nums1[i]与nums2[i]得到的增益是(nums2[i] - nums1[i])。我们要找的是一个子数组,使得这个增益最大化。这可以通过Kadane算法实现,即计算最大子数组和,然后将这个最大增益加到原始数组nums1的总和上。为了确保考虑了所有可能,还需要从nums2的角度做同样的计算,即将nums1与nums2的角色互换,再次计算最大增益并加到nums2的总和上。最后,比较这两种情况的结果,取最大值。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
为什么在计算增益时,使用的是(nums2[i] - nums1[i]),这里的逻辑是什么?
▷🦆
Kadane算法通常用于寻找最大子数组和,如何确保这里应用Kadane算法来计算增益是合适的?
▷🦆
在解法中提到的`如果当前子数组和小于0,重置为0`,这样做的目的是什么?
▷🦆
题解中提到要从nums1和nums2两个角度分别计算,这种方法是否总是能保证找到全局最优解?
▷