LeetCode#689 Maximum Sum of 3 Non-Overlapping Subarrays(week18)

本文针对LeetCode上的“三个不重叠子数组的最大和”问题提供了一种有效的解决方案。通过两次遍历数组,先计算所有可能的长度为k的子数组之和,然后确定三个不重叠子数组的组合,以获得最大的总和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

week18

题目

In a given array nums of positive integers, find three non-overlapping subarrays with maximum sum.

Each subarray will be of size k, and we want to maximize the sum of all 3*k entries.

Return the result as a list of indices representing the starting position of each interval (0-indexed). If there are multiple answers, return the lexicographically smallest one.
这里写图片描述
Note:
nums.length will be between 1 and 20000.
nums[i] will be between 1 and 65535.
k will be between 1 and floor(nums.length / 3).
原题地址:https://leetcode.com/problems/maximum-sum-of-3-non-overlapping-subarrays/description/

解析

题目要求给定一个数组和常数k,找出三个不重叠的长度为k的子数组使得这三个子数组的和最大。
大致思路是先遍历一次数组得到以每个位置为起始位置的长度为k的数组的和,再遍历一次,每次固定以当前位置为起始位置的子数组作为三个数组中的中间一个,找到当前情况下的第一个和第三个数组使得和最大,如果该情况大于先前得到的以其他位置为中间数组起始位置的和的最大值,则记录三个数组的起始位置并将最大值替换。

代码

class Solution {
public:
    vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
        int len = nums.size();
        int maxSum = 0;
        vector<int> res(3, -1);
        vector<int> sum;
        Sum(nums, sum, k);
        for (int i = k; i <= (len - 2 * k); ++i) {
            int end = i - k;
            int pos1;
            // 找到固定了以i为起始位置的子串作为三个子串的中间子串,第一个子串的最大值
            findLargest(sum, 0, end, pos1);
            int begin = i + k;
            int pos2;
            // 找到固定了以i为起始位置的子串作为三个子串的中间子串,第三个子串的最大值
            findLargest(sum, begin, len - k, pos2);
            // 以i为起始位置的子串作为三个子串的中间子串
            // tmp为该种情况所能达到的最大值
            int tmp = sum[pos1] + sum[i] + sum[pos2];
            if (tmp > maxSum) {
                maxSum = tmp;
                res[0] = pos1;
                res[1] = i;
                res[2] = pos2;
            }
        }
        return res;
    }
    // 返回以每个位置为起始点的子串的和
    void Sum(vector<int>& nums, vector<int>& sum, int k) {
        sum.clear();
        int len = nums.size();
        int tmp = 0;
        for (int i = 0; i < k; ++i) {
            tmp += nums[i];
        }
        sum.push_back(tmp);
        for (int i = 1; i <= (len - k); ++i) {
            tmp = tmp - nums[i - 1] + nums[i + k - 1];
            sum.push_back(tmp);
        }
    }
    // 返回从起始位置为begin到起始位置为end的子串的和中的最大值
    // pos记录该起始位置
    void findLargest(vector<int>& sum, int begin, int end, int& pos) {
        pos = begin;
        int largest = sum[begin];
        for (int i = begin + 1; i <= end; ++i) {
            if (sum[i] > largest) {
                largest = sum[i];
                pos = i;
            }
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值