三、K 次串联后最大子数组之和(Weekly Contest 154)

题目描述:
给你一个整数数组 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

我感觉比赛的时候思路是没有问题的,首先应该判断每个里面是不是都大于等于0,如果满足,那么就是sum*k(sum表示的是一个arr之和),如果不是的话,判断arr中是不是所有的数字都小于0,如果都小于0那么返回0,如果sum大于0,那么需要考虑的是将两个拼接起来,然后用dp求和,将后面(k-2)*sum然后加入到拼接两个吼的大小

class Solution {
    public int kConcatenationMaxSum(int[] arr, int k) {
        int sum = 0;
		boolean isallminus = false;
		boolean isalldayuze = true;
		for (int i : arr) {
			sum += i;
			if(i > 0){
				isallminus = true;
			}
			if(i < 0){
				isalldayuze = false;
			}
		}
		if(!isallminus){
			return 0;
		}
		long result = 0;
		long mod = 100000000 + 7;
		
//		每个数字都大于等于0,那么总和就是所有加起来
		for (int i = 0; i < k; i++) {
			result += sum;
			result %= mod;
		}
		if(isalldayuze){
			return (int) result;
		}
//		先计算将所有可能的情况都扩展一遍
		long tem1 = 0;
		for (int i = 0; i < k; i++) {
			tem1 += sum;
			tem1 %= mod;
		}
//		扩展一个即可
		int [] temarray = new int[arr.length * 2];
		for (int i = 0; i < temarray.length; i++) {
			temarray[i] = arr[i % arr.length];
		}
		long tem2 = 0;
		long [] dp = new long[temarray.length];
		dp[0] = temarray[0];
		for (int i = 1; i < dp.length; i++) {
			if(dp[i - 1] < 0){
				dp[i] = temarray[i];
				continue;
			}else {
				dp[i] = dp[i - 1] + temarray[i];
				dp[i] %= mod;
			}
		}
		for (long l : dp) {
			tem2 = Math.max(l, tem2);
		}
		if(sum > 0){
			for (int i = 0; i < k - 2; i++) {
				tem2 += sum;
				tem2 %= mod;
			}
		}
		return (int) Math.max(tem2, Math.max(tem1, result));
    }
}

感觉我的代码还是有点问题的,虽然你连接了两个来取出最大值,但是你没有考虑拼接后面的因此有点问题:
看看别人AC的代码

class Solution {
    public int kConcatenationMaxSum(int[] arr, int k) {
        long sum = 0;
        for (int a: arr) sum += a;
        int mod = 1000000007;
        long res = 0;
        int n = arr.length;
        int[] dp = new int[n+1];
        for (int i = 0; i < n; i++) {
            dp[i + 1] = Math.max(dp[i] + arr[i], arr[i]);
            res = Math.max(res, dp[i+1]);
        }
        if (k == 1) 
            return (int) (res % mod);
        long first = arr[0];
        int cur = 0;
        for (int i = 0; i < n; i++) {
            cur += arr[i];
            first = Math.max(first, cur);
        }
        System.out.println(dp[n]);
        res = Math.max(res, first + dp[n]);
        if (sum > 0) {
            long tmp = sum * (k - 2) + dp[n] + first;
            res = Math.max(res, tmp);
        }
        return (int) (res % mod);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值