前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LWC 52:689. Maximum Sum of 3 Non-Overlapping Subarrays

LWC 52:689. Maximum Sum of 3 Non-Overlapping Subarrays

作者头像
用户1147447
发布2018-01-02 10:59:10
6670
发布2018-01-02 10:59:10
举报
文章被收录于专栏:机器学习入门

LWC 52:689. Maximum Sum of 3 Non-Overlapping Subarrays

传送门:689. Maximum Sum of 3 Non-Overlapping Subarrays

Problem:

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.

Example:

Input: [1,2,1,2,6,7,5,1], 2 Output: [0, 3, 5] Explanation: Subarrays [1, 2], [2, 6], [7, 5] correspond to the starting indices [0, 3, 5]. We could have also taken [2, 1], but an answer of [1, 3, 5] would be lexicographically larger.

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).

思路: dp[i]:表示从i下标开始,长度为k的subArray的和。dp[i] = nums[i] + nums[i+1]+...+nums[i+k-1],这样给定当前坐标i,只需要求出位于左侧的最大max{dp[i'] | i' <= i - k}记录之,同理求出右侧的最大max{dp[j] | j >= i + k}

代码如下:

代码语言:javascript
复制
    public int[] maxSumOfThreeSubarrays(int[] nums, int k) {
        int n = nums.length;
        int[] sum = new int[n + 1];
        // 累加和,区间计算时,只需O(1)
        for (int i = 0; i < n; ++i) {
            sum[i + 1] = nums[i] + sum[i]; 
        }

        int[] dp = new int[n];

        // 对应最后一个区间的选择范围
        for (int l = 2 * k; l + k <= n; ++l) {
            dp[l] = sum[l + k] - sum[l];
        }

        // 对应第二个区间的选择范围
        for (int l = k; l + 2 * k <= n; ++l) {
            dp[l] = sum[l + k] - sum[l];
        }

        // 对应第一个区间的选择范围
        for (int l = 0; l + 3 * k <= n; ++l) {
            dp[l] = sum[l + k] - sum[l];
        }

        // 记录当前i下,符合i' <= i - k的dp[i']中最大下标
        int[] left = new int[n];
        for (int i = 0; i < n; ++i) {
            if (i - k >= 0) {
                if (left[i - 1] == -1) {
                    left[i] = i - k;
                }
                else if (dp[i - k] <= dp[left[i - 1]]) {
                    left[i] = left[i - 1];
                }
                else{
                    left[i] = i - k;
                }
            }
            else {
                left[i] = -1; //表示当前i的左侧没有合法的i'
            }
        }

        // 记录当前i下,符合j >= i + k的dp[j]中最大下标
        int[] right = new int[n];
        for (int i = n - 1; i >= 0; --i) {
            if (i + k < n) {
                if (right[i + 1] == -1) {
                    right[i] = i + k;
                }
                else if (dp[right[i + 1]] > dp[i + k]) {
                    right[i] = right[i + 1];
                }
                else {
                    right[i] = i + k;
                }
            }
            else {
                right[i] = -1; //表示当前i的右侧没有合法的j
            }
        }

        int max = 0;
        int[] res = {-1, -1, -1};
        for (int i = 0; i < n; ++i) {
            if (left[i] != -1 && right[i] != -1) {
                int tmp = dp[i] + dp[right[i]] + dp[left[i]];
                if (tmp > max) {
                    max = dp[i] + dp[right[i]] + dp[left[i]];
                    res[0] = left[i];
                    res[1] = i;
                    res[2] = right[i];
                }
            }
        }
        return res;
    }

注意求解left和right中选取最大值的if判断,一个有等号,一个无等号,是为了 return the lexicographically smallest one.

精简版本:

代码语言:javascript
复制
    public int[] maxSumOfThreeSubarrays(int[] nums, int k) {
        int n = nums.length;
        int[] sum = new int[n + 1];
        for (int i = 0; i < n; ++i) {
            sum[i + 1] = nums[i] + sum[i]; 
        }

        int[] dp = new int[n];

        for (int i = 0; i + k <= n; ++i){
            dp[i] = sum[i + k] - sum[i];
        }

        int[] left = new int[n];
        Arrays.fill(left, -1);
        for (int i = k; i < n; ++i) {
            if (i - k == 0 || dp[i - k] > dp[left[i - 1]]) {
                left[i] = i - k;
            }
            else {
                left[i] = left[i - 1];
            }
        }

        int[] right = new int[n];
        Arrays.fill(right, -1);
        for (int i = n - k - 1; i >= 0; --i) {
            if (i + k == n - 1 || dp[right[i + 1]] <= dp[i + k]){
                right[i] = i + k;    
            }
            else{
                right[i] = right[i + 1];
            }
        }

        int max = 0;
        int[] res = {-1, -1, -1};
        for (int i = 0; i < n; ++i) {
            if (left[i] != -1 && right[i] != -1) {
                int tmp = dp[i] + dp[right[i]] + dp[left[i]];
                if (tmp > max) {
                    max = dp[i] + dp[right[i]] + dp[left[i]];
                    res[0] = left[i];
                    res[1] = i;
                    res[2] = right[i];
                }
            }
        }
        return res;
    }    
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-10-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • LWC 52:689. Maximum Sum of 3 Non-Overlapping Subarrays
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档