【我也想刷穿 LeetCode】689. 三个无重叠子数组的最大和

49 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

现在前端很多岗位面试需要有一定的算法基础,或者说经常刷算法的会优先考虑。

因此每天刷刷LeetCode非常有必要

在这之前我也刷过一些算法题,也希望以后也坚持刷,跟某掘友一样,我也想刷穿 LeetCode

一、题目描述

给你一个整数数组 nums 和一个整数 k ,找出三个长度为 k 、互不重叠、且全部数字和(3 * k 项)最大的子数组,并返回这三个子数组。

以下标的数组形式返回结果,数组中的每一项分别指示每个子数组的起始位置(下标从 0 开始)。如果有多个结果,返回字典序最小的一个。

 

示例 1:

输入:nums = [1,2,1,2,6,7,5,1], k = 2
输出:[0,3,5]
解释:子数组 [1, 2], [2, 6], [7, 5] 对应的起始下标为 [0, 3, 5]。
也可以取 [2, 1], 但是结果 [1, 3, 5] 在字典序上更大。

二、思路分析

我们先预处理获得所有长度为k的子数组的和

对于这里面的所有和,我们要取不能相邻k个内的三个,和最大的值

说白了就是每k个最多取一个,跟打家劫舍的背包大同小异,只是需要记录路径的坐标

我们用动态规划,分别维护当前取第一个的最大值和坐标,取第二个的最大值和坐标和取第三个的最大值和坐标即可

三、代码实现

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var maxSumOfThreeSubarrays = function(nums, k) {
    var lMax = function(l1, l2){
        if(l1[0] > l2[0])
            return l1
        return l2
    }

    const windows = new Array(nums.length - k + 1)
    for(let i=0,j=0,s=0;i<=nums.length;i++){
        if(i < k)
            s += nums[i]
        else{
            windows[j++] = s
            if(i<nums.length)
                s += nums[i] - nums[i-k]
        }
    }
    const dp = new Array(windows.length)
    for(let i=0;i<dp.length;i++){
        dp[i] = new Array(3)
        for(let j=0;j<3;j++)
            dp[i][j] = [0]
    }
        
    for(let i=0;i<windows.length;i++)
        if(i < k)
            if(i > 0)
                dp[i][0] = lMax([windows[i], i], dp[i-1][0])
            else
                dp[i][0] = [windows[i], i]
        else{
            dp[i][0] = lMax([windows[i], i], dp[i-1][0])
            dp[i][1] = lMax([dp[i-k][0][0]+windows[i], dp[i-k][0][1], i], dp[i-1][1])
            if(i >= 2 * k)
                dp[i][2] = lMax([dp[i-k][1][0] + windows[i], dp[i-k][1][1], dp[i-k][1][2], i], dp[i-1][2])
        }
    let m = 0;
    let ans = new Array(3);
    for(let i=0;i<windows.length;i++)
        if(dp[i][2][0] > m){
            m = dp[i][2][0];
            for(let j=0;j<3;j++)
                ans[j] = dp[i][2][j+1];
        }
    return ans;
};


四、总结

以上就是本道题的所有内容了,本系列会持续更,欢迎点赞、关注、收藏,另外如有其他的问题,欢迎下方留言给我,我会第一时间回复你,感谢~