LeetCode689. Maximum Sum of 3 Non-Overlapping Subarrays

Solution1: Divide and Conquer

This question asks for the three non-overlapping intervals with maximum sum. So this can be divided into 3 parts -- find 3 non-overlapping intervals respectively, and combining the results to get the 3 non-overlapping intervals we want. Since each interval is of length k, suppose the start index of the middle interval is i, then the range of i's value is: k <=i <= n-2k. Actually this i has also indicated the limits of the range of the first interval and the range of the last interval. Hence we have the following DP components:

left[i] stores the start index for the first interval in range [0, i]
right[i] stores the start index for the third interval in range [i, n - 1]

After that we can test every possible start index of middle interval, i.e. k <= i <= n - 2k. And based on the above 2 DP results, we can easily get the first and third max sum intervals. The runtime of this process is O(n).

Note that this question asks for the lexicographical smallest order interval, that is, when there are two intervals with the same max sum, we always select the leftmost one. So in this solution, for the first interval, since we are iterating from left to right, the comparison if statement use currSum > total. And for the third interval, we are iterating from right to left, the comparison if statement use currSum >= total.

Another trick we use here, to ensure the algorithm runs in O(n) time, is that we use predix sum to get the sum of a consecutive subarray in O(1) time. Otherwise, if we calaulate the interval sum each time, that would be O(k) time for each interval.

Run time complexity of this algorithm is O(n). Space complexity is O(n). n is the length of the input nums array.

class Solution {
    public int[] maxSumOfThreeSubarrays(int[] nums, int k) {
        int n = nums.length;
        int[] sum = new int[n + 1];
        int[] left = new int[n];
        int[] right = new int[n];
        int[] ret = new int[3];
        
        // First get the prefix sum of nums.
        // Prefix sum enables us to get the sum of k consecutive element in O(1) time
        for (int i = 0; i < n; i++) {
            sum[i + 1] = sum[i] + nums[i];
        }
        
        // DP for the left intetval max sum
        for (int i = k, tot = sum[k] - sum[0]; i < n; i++) {
            if (sum[i + 1] - sum[i - k + 1] > tot) {
                tot = sum[i + 1] - sum[i - k + 1];
                left[i] = i - k + 1;
            } else {
                left[i] = left[i - 1];
            }
        }
        
        // DP for the right interval max sum
        right[n - k] = n - k;
        for (int i = n - 1 - k, tot = sum[n] - sum[n - k]; i >= 0; i--) {
            if (sum[i + k] - sum[i] >= tot) {
                tot = sum[i + k] - sum[i];
                right[i] = i;
            } else {
                right[i] = right[i + 1];
            }
        }
        
        // Find the max sum by iterating through the middle interval index based on above 2 cache.
        int maxSum = 0;
        for (int i = k; i <= n - 2 * k; i++) {
            int l = left[i - 1], r = right[i + k];
            int tot = sum[l + k] - sum[l] + sum[r + k] - sum[r] + sum[i + k] - sum[i];
            if (tot > maxSum) {
                ret[0] = l;
                ret[1] = i;
                ret[2] = r;
                maxSum = tot;
            }
        }
        
        return ret;
    }
}

Solution2: Generalized method

This is a generalized method for 689. Maximum Sum of 3 Non-Overlapping Subarrays
.

In this solution, dp[i][j] is used for recording for ith interval, what are the max sums for first j numbers in each position. And index[i][j] is used for recording for ith interval, what are the current start index for first j numbers that made up the max sum.

Thus after the searching ends, dp[n][nums.length] stores the max sum we can get and index[n][nums.length] stores the start index of last interval for the max sum. And now we can search backwards for each previous start index based on the start index of current interval. Because the start index of previous interval is the index stored in index[i - 1][current start index], which is the max sum of the subarray before current start index.

Run time complexity is O(n * len) where n is the number of intervals needed and len is the length of input array.

Space complexity is O(n * len) as well.

class MaxSumOfThreeSubarrays {
    /**
     * 
     * @param nums input array of numbers
     * @param k length of each interval
     * @param n number of intervals 
     * @return start index of each interval that has the maximum sum
     */
    public int[] maxSumOfThreeSubarrays(int[] nums, int k, int n) {
        int[][] dp = new int[n + 1][nums.length + 1];
        int[][] index = new int[n + 1][nums.length + 1];
        int tot = 0;
        // prefix sum
        int[] sum = new int[nums.length + 1];
        for (int i = 0; i < nums.length; i++) {
            sum[i + 1] = nums[i] + sum[i];
        }
        
        for (int i = 1; i <= n; i++) {
            for (int j = k - 1; j < nums.length; j++) {
                int tmpMax = sum[j + 1] - sum[j - k + 1] + dp[i - 1][j - k + 1];
                if (tmpMax > dp[i][j]) {
                    dp[i][j + 1] = tmpMax;
                    index[i][j + 1] = j - k + 1;
                } else {
                    dp[i][j + 1] = dp[i][j];
                    index[i][j + 1] = index[i][j];
                }
            }
        }
        
        int[] ret = new int[n];
        int prev = nums.length;
        for (int i = n; i > 0; i--) {
            ret[i - 1] = index[i][prev];
            prev = ret[i - 1];
        }
        
        return ret;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 迈开脚步走向从前 忧愁的结局有个鲜明的开始 年少无知与自然最为洁净的时刻 背上长着一对眼睛 一意孤行 画一个圆圈的...
    顽尘阅读 327评论 2 4
  • 参考 Golang 构建 HTTP 服务server.go 源码 HTTP 网络发展,很多网络应用都是构建在 HT...
    找不到工作阅读 1,827评论 0 0
  • 但是有时候我们都傻傻的相信自己的眼睛,而以至于他对于你的好,蒙蔽了你心一般。 一直都想写一个关于咖啡和爱情的故事,...
    静静地聆听Yang阅读 840评论 0 1
  • 社会发展越来越快了。而衡量社会发展的标准出了金钱还有什么更合适的吗?没有,绝对没有了!现在的三线城市的月消费都是...
    昕昕向上阅读 316评论 0 0
  • iOS 使用第三方网络请求AFNetworking 以ContentType:application/x-www-...
    bogo阅读 1,292评论 0 1