[LeetCode] 689. Maximum Sum of 3 Non-Overlapping Subarrays

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


  • Thought process:
    Dynamic programming.
    1. Create an array of sums of windows of size k. This array's length will be nums.length - k + 1, because an array can have this many choices of windows.
    2. Iterate through the windows and find the index of the window with the max sum to the left and to the right.
    3. Iterate through the windows again and get and three windows with max sum.

    Solution:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    class Solution {
        public int[] maxSumOfThreeSubarrays(int[] nums, int k) {
            int[] win = new int[nums.length - k + 1];
            int sum = 0;
            for (int i = 0; i < nums.length; i++) {
                sum += nums[i];
                if (i >= k) {
                    sum -= nums[i - k];
                }
                if (i >= k - 1) {
                    win[i - (k - 1)] = sum;
                }
            }
            
            int j = 0;
            int[] left = new int[win.length];
            for (int i = 0; i < win.length; i++) {
                if (win[i] > win[j]) {
                    j = i;
                }
                left[i] = j;
            }
            
            j = win.length - 1;
            int[] right = new int[win.length];
            for (int i = win.length - 1; i >= 0; i--) {
                if (win[i] >= win[j]) {
                    j = i;
                }
                right[i] = j;
            }
            
            int[] max = new int[]{ -1, -1, -1 };
            for (int b = k; b < win.length - k; b++) {
                int a = left[b - k];
                int c = right[b + k];
                if (max[0] == -1 || win[a] + win[b] + win[c] > win[max[0]] + win[max[1]] + win[max[2]]) {
                    max[0] = a;
                    max[1] = b;
                    max[2] = c;
                }
            }
            return max;
        }
    }
    

    Time complexity: O(n).

    Comments

    1. your right function wrong dude.
      if (win[i] > win[j]) {
      j = i;
      }
      should be
      if (win[i] >= win[j]) {
      j = i;
      }
      since the answer is
      If there are multiple answers, return the lexicographically smallest one.

      ReplyDelete
    2. what if they asked for m subarray in general?

      ReplyDelete

    Post a Comment

    Popular posts from this blog

    [LeetCode] 269. Alien Dictionary

    [HackerRank] Roads and Libraries

    [LeetCode] 631. Design Excel Sum Formula