【题目】*1191. K 次串联后最大子数组之和
53.最大子序和
*152. 乘积最大子数组
*1186. 删除一次得到子数组最大和
*1191. K 次串联后最大子数组之和
给你一个整数数组 arr 和一个整数 k。
首先,我们要对该数组进行修改,即把原数组 arr 重复 k 次。
举个例子,如果 arr = [1, 2] 且 k = 3,那么修改后的数组就是 [1, 2, 1, 2, 1, 2]。
然后,请你返回修改后的数组中的最大的子数组之和。
注意,子数组长度可以是 0,在这种情况下它的总和也是 0。
由于 结果可能会很大,所以需要 模(mod) 10^9 + 7 后再返回。
示例 1:
输入:arr = [1,2], k = 3
输出:9
示例 2:
输入:arr = [1,-2,1], k = 5
输出:2
示例 3:
输入:arr = [-1,-2], k = 7
输出:0
提示:
1 <= arr.length <= 10^5
1 <= k <= 10^5
-10^4 <= arr[i] <= 10^4
【解题思路1】
- k = 1: max = 最大子串
- k >= 1:
如果数组和>0:max = 最大后子串 + (k - 2)*数组和 + 最大前子串
如果数组和<=0:max = 最大后子串 + 最大前子串 - 最后max与最大子串做对比,取最大值
会因为int类型溢出而解答错误
class Solution {
public long MaxSub(int[] arr, int len){
// 求最大子串
long maxEndNow = 0;
long maxSub = 0;
for(int i = 0; i < len; i++) {
maxEndNow = Math.max(maxEndNow + arr[i], 0);
maxSub = Math.max( maxSub, maxEndNow);
}
return maxSub;
}
public int kConcatenationMaxSum(int[] arr, int k) {
int i;
long sum, res;
long maxSub=0;
long maxPre=0;
long maxPost=0;
int len = arr.length;
if(arr == null || len == 0) {
return 0;
}
sum = 0;
// 得到数组和
for(i = 0; i < len; i++) {
sum = sum + arr[i];
}
// 得到最大前子串
sum = 0;
for(i = 0; i < len; i++) {
sum = sum + arr[i];
maxPre = Math.max( maxPre, sum);
}
// 得到最大后子串
sum = 0;
for(i = len - 1; i >= 0; i--) {
sum = sum + arr[i];
maxPost = Math.max( maxPost, sum);
}
// 得到最大子串
maxSub = MaxSub(arr, len);
if(k == 1) {
res = maxSub;
} else {
if(sum > 0) {
res = maxPost + (k - 2) * sum + maxPre;
} else {
res = maxPost + maxPre;
}
res = Math.max(res, maxSub);
}
return (int)res % 1000000007;
}
}
【解题思路2】动态规划 - Kadane算法(待研究)
class Solution {
public int kConcatenationMaxSum(int[] arr, int k) {
if (arr == null || arr.length == 0){
return 0;
}
long maxOfEnd = arr[0] > 0 ? arr[0] : 0L;
long maxSoFar = maxOfEnd;
long sum = arr[0];
for (int i = 1; i < Math.min(k, 2) * arr.length; i++) {
maxOfEnd = Math.max(maxOfEnd + arr[i % arr.length], arr[i % arr.length]);
maxSoFar = Math.max(maxOfEnd, maxSoFar);
if (i < arr.length){
sum += arr[i];
}
}
while (sum > 0 && --k >= 2)
maxSoFar = (maxSoFar + sum) % 1000000007;
return (int) maxSoFar;
}
}