每日写题分享--三个无重叠子数组的最大和//三个滑动窗口的配合

该博客介绍了如何使用滑动窗口算法解决寻找数组中三个无重叠子数组的最大和问题。首先从求解单个长度为K的子数组最大和开始,然后扩展到两个无重叠子数组,最后解决三个子数组的情况。每个阶段都通过维护窗口内的元素和,更新最大和及对应起始位置来实现。代码示例展示了具体的实现过程。
摘要由CSDN通过智能技术生成

题目描述:

示例:

题目链接戳此

 解题思路:

求三个无重叠子数组的最大和,可以先从求一个长度为K的子数组的最大和开始思考。

  • 一个子数组的最大值

用sum1记录当前窗口元素的和,maxSum1更新最大的sum1。并且用长度为1的数组记录下最大和的起始位置。滑动窗口一直在走,所以sum是一直在变化的,加上后面的元素同时要记得减去前面的元素才能叫滑动窗口。

代码实现如下:

public int[] maxSumOfOneSubarray(int[] nums, int k) {
        int[] ans = new int[1];
        int sum1 = 0, maxSum1 = 0;
        for (int i = 0; i < nums.length; i++) {
            sum1 += nums[i];
            if (i >= k - 1) {
                if (sum1 > maxSum1) {
                    maxSum1 = sum1;
                    ans[0] = i - k + 1;
                }
                sum1 -= nums[i - k + 1];
            }
        }
        return ans;
    }
  • 两个无重叠子数组的最大和

在知道一个数组的最大和怎么求之后求两个就很方便了。模拟两个窗口大小为k的滑动窗口,一个边界为【0,k - 1】,第二个窗口边界为【k,2 * k - 1】,sum1记录第一个窗口的和,sum2记录第二个窗口的和。maxSum1更新第一个窗口的最大和,maxSum12更新两个窗口的最大和。并且记录下两个窗口的最大和的下标。代码实现如下:

public int[] maxSumOfTwoSubarrays(int[] nums, int k) {
        int[] ans = new int[2];
        int sum1 = 0, maxSum1 = 0, maxSum1Idx = 0;
        int sum2 = 0, maxSum12 = 0;
        for (int i = k; i < nums.length; i++) {
            sum1 += nums[i - k];
            sum2 += nums[i];
            if (i >= k * 2 - 1) {
                if (sum1 > maxSum1) {
                    maxSum1 = sum1;
                    maxSum1Idx = i - k * 2 + 1;//更新第一个窗口的最大和下标
                }
                if (maxSum1 + sum2 > maxSum12) {
                    maxSum12 = maxSum1 + sum2;
                    ans[0] = maxSum1Idx;//放进数组
                    ans[1] = i - k + 1;
                }
                sum1 -= nums[i - k * 2 + 1];//窗口一直在滑动,sum也一直在改变
                sum2 -= nums[i - k + 1];
            }
        }
        return ans;
    }
  • 两个无重叠子数组的最大和

下面回归本题,知道两个无重叠子数组的最大和怎么求之后,求三个就只要增加几个元素即可,

先看边界,第一个窗口【0,k - 1】,第二个窗口【k,2 * k - 1】,第三个窗口【2 * k,3 * k - 1】.同样的,sum1,sum2,sum3记录三个窗口格子元素的和,maxSum1更新第一个窗口的最大和并记录下位置,maxSum12更新前两个窗口的最大和,更新两个下标位置。total记录三个窗口最大和,并且用大小为3的数组ans记录并更新三个下标位置。

代码实现如下:

public int[] maxSumOfThreeSubarrays(int[] nums, int k) {
        int[] ans = new int[3];
        int sum1 = 0,maxSum1 = 0,sum1Index = 0;
        int sum2 = 0,maxSum12 = 0,maxSum2Index1 = 0,maxSum2Index2 = 0;
        int sum3 = 0,total = 0;
        for (int i = 2 * k;i < nums.length;i++) {
            sum1 += nums[i - 2* k];
            sum2 += nums[i - k];
            sum3 += nums[i];
            if (i >= 3 * k - 1) {
                if (sum1 > maxSum1) {
                    maxSum1 = sum1;
                    sum1Index = i - 3 * k + 1;
                }
                if (maxSum1 + sum2 > maxSum12) {
                    maxSum12 = maxSum1 + sum2;
                    maxSum2Index1 = sum1Index;
                    maxSum2Index2 = i - 2 * k + 1;
                }
                if (maxSum12 + sum3 > total) {
                    total = maxSum12 + sum3;
                    ans[0] = maxSum2Index1;
                    ans[1] = maxSum2Index2;
                    ans[2] = i - k + 1;
                }
                sum1 -= nums[i - 3 * k + 1];
                sum2 -= nums[i - 2 *k + 1];
                sum3 -= nums[i - k + 1];
            }
        }
        return ans;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值