zoukankan      html  css  js  c++  java
  • [Leetcode]689.Maximum Sum of 3 Non-Overlapping Subarrays

    链接:LeetCode689

    给定数组 nums 由正整数组成,找到三个互不重叠的子数组的最大和。

    每个子数组的长度为k,我们要使这3*k个项的和最大化。

    返回每个区间起始索引的列表(索引从 0 开始)。如果有多个结果,返回字典序最小的一个。

    示例:

    输入: ([1,2,1,2,6,7,5,1], 2)
    输出: ([0, 3, 5])
    解释: 子数组 ([1, 2], [2, 6], [7, 5]) 对应的起始索引为 ([0, 3, 5])
    我们也可以取 ([2, 1]), 但是结果 ([1, 3, 5]) 在字典序上更大。

    相关标签:动态规划

    又是一道明确是用动态规划解法后,便不难想出动态转移方程的题目。
    下面考虑一般情况,也就是求解划分成(N)个不重叠数组的最大和。
    假设到第(i)个元素为止,一共已经产生了(j)个不重叠数组,那么令$ dp[i][j] (表示这)j(个不重叠数组的最大和。 然后就要寻找状态转移方程。**对于第)i$个元素,分为两种情况,可取可不取。**
    如果取,那就说明 (nums[i]) 是第(j)个子数组的最后一个元素,那么转移方程为:

    [dp[i][j] = dp[i-k][j-1]+nums_{i-k+1:i} ]

    也就是说,从(i-k+1)(i),这(k)个元素构成了第(j)个子数组,那我们只需要求到第(i-k)个元素为止,产生(j-1)个不重叠数组的最大和即可。
    如果不取,那问题就变成了求到第(i-1)个元素为止,产生(j)个不重叠数组的最大和,那么转移方程为:

    [dp[i][j] = dp[i-1][j] ]

    当然这题的难度还在于,需要你还原出最大和的情况下,所有子数组的起始元素下标,所以需要另外用一个数组保存一下每一步的最优下标。
    同样,假设到第(i)个元素为止,一共已经产生了(j)个不重叠数组,用(path[i][j])表示第(j)个子数组的末尾元素下标。
    那么按照上面的推断,如果取第(i)个元素,那么(path[i][j]=i);否则的话 (path[i][j]=path[i-1][j])。最后就是根据 path 数组还原答案了。

    其代码如下:

    python:

    class Solution:
        def maxSumOfThreeSubarrays(self, nums: List[int], k: int) -> List[int]:
            n = len(nums)
            dp = [[0 for j in range(4)] for i in range(n+1)]
            path = [[0 for j in range(4)] for i in range(n+1)]
            cur = sum(nums[:k])
            sums = [cur]
            for i in range(k,n):
                cur += nums[i] - nums[i-k]
                sums.append(cur)
    
            for i in range(1,n+1):
                for j in range(1,4):
                    if i < j*k:
                        dp[i][j] = 0
                        continue
                    dp[i][j] = dp[i-1][j]
                    path[i][j] = path[i-1][j]
                    if dp[i-k][j-1] + sums[i-k] > dp[i][j]:
                        dp[i][j] = dp[i-k][j-1] + sums[i-k]
                        path[i][j] = i-k
    
            res = []
            ind = n
            for j in reversed(range(1,4)):
                res.append(path[ind][j])
                ind = path[ind][j]
            res.reverse()
            return res
    

    C++:

    class Solution {
    public:
        vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
            int n = nums.size();
            vector<vector<int>> dp(n+1,vector<int>(4,0));
            vector<vector<int>> path(n+1,vector<int>(4,0));
            int cur = accumulate(nums.begin(),nums.begin()+k,0);
            vector<int> sums{cur};
            for(int i=k;i<n;++i){
                cur += nums[i]-nums[i-k];
                sums.push_back(cur);
            }
            for(int i=1;i<n+1;++i){
                for(int j=1;j<4;++j){
                    if(i<j*k){
                        continue;
                    }
                    dp[i][j] = dp[i-1][j];
                    path[i][j] = path[i-1][j];
                    if(dp[i-k][j-1]+sums[i-k]>dp[i][j]){
                        dp[i][j] = dp[i-k][j-1]+sums[i-k];
                        path[i][j] = i-k;
                    }
                }
            }
            vector<int> res;
            int ind = n;
            for (int j=3;j>0;--j){
                res.insert(res.begin(),path[ind][j]);
                ind = path[ind][j];
            }
            return res;
        }
    };
    

    参考:[LeetCode 689]三个无重叠子数组的最大和

  • 相关阅读:
    mysql5.7.22安装步骤
    idea 配置http代理
    大话设计模式之类与类之间的关系读后感
    大话设计模式之工厂方法模式读后感
    rabbitmq+java入门(五)Topic
    rabbitmq+java入门(四)routing
    rabbitmq+java入门(二) 工作队列
    rabbitmq+java入门(三)exchange的使用
    rabbitmq+java入门(一)hello world
    idea+jrebel+springboot热部署
  • 原文地址:https://www.cnblogs.com/hellojamest/p/12273782.html
Copyright © 2011-2022 走看看