[leetcode]Maximum Sum of 3 Non-Overlapping Subarrays

本文介绍了一种通过动态规划解决给定数组中寻找三个不重叠子数组以获得最大和的方法,并提供了详细的算法实现步骤。

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

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.



题目的意思是: 给定一个数组,找到其中3个不相互覆盖的子串,使其和最大,返回3个子串的位置。如果子串和相等,返回最前面的子串位置。给定子串的长度为k。

做法:动态规划。首先对数组预处理,以k为基准,得到一个子串求和的数组new_nums。对这个数组进行动态规划。dp[i][j]代表 以i为结尾,个数为j的最大值。转移方程是 dp[i][j] = max(dp[0][j-1],...,dp[i - k][j-1]) + new_nums[i]; 但是,这么做复杂度是O(n*n)。数据有2w个,不一定能过。使用一个变量cnt_max,记录从第一个位置到(i-k)的最大值,如果大于cnt_max的值时,则更新。 最后,利用dp和new_nums得到子串的位置。


class Solution {
public:
    vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
        int dp[20010][4];
        memset(dp, 0, sizeof(dp));
        int n = nums.size();
        int new_n = n - k + 1;
        vector <int> answer(3);
        int max_sum = 0;
        int max_id;
        vector <int> new_nums;
        int cnt = 0;
        for(int i=0;i<k;i++){
            cnt += nums[i];
        }
        new_nums.push_back(cnt);
        for(int i=0;i<new_n - 1;i++){
            cnt = cnt - nums[i] + nums[i + k];
            new_nums.push_back(cnt);
        }
        
        for(int i =0;i<new_n;i++){
            dp[i][1] = new_nums[i];
        }
        int cnt_max = 0;
        for(int i = k; i < new_n; i++){
            if( dp[i - k][1] > cnt_max ){
                cnt_max = dp[i - k][1];
            }
            dp[i][2] = cnt_max + new_nums[i];
        }
        cnt_max = 0;
        for(int i = 2 * k; i < new_n; i++){
            if( dp[i - k][2] > cnt_max ){
                cnt_max = dp[i - k][2];
            }
            dp[i][3] = cnt_max + new_nums[i];
            if(dp[i][3] > max_sum){
                max_sum = dp[i][3];
                max_id = i;
            }
        }
        answer[2] = max_id;
        int now_sum = max_sum - new_nums[max_id];
        for(int i = 0; i< new_n; i++){
            if( dp[i][2] == now_sum){
                answer[1] = i;
                now_sum -= new_nums[i];
                break;
            }
        }
        for(int i=0; i< new_n; i++){
            if(dp[i][1] == now_sum){
                answer[0] = i;
                break;
            }
        }
        return answer;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值