Skip to content

53. Maximum Subarray 👍

Approach 1: 1D DP

  • Time: $O(n)$
  • Space: $O(n)$
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Solution {
 public:
  int maxSubArray(vector<int>& nums) {
    // dp[i] := max sum subarray ending w/ i
    vector<int> dp(nums.size());

    dp[0] = nums[0];
    for (int i = 1; i < nums.size(); ++i)
      dp[i] = max(nums[i], dp[i - 1] + nums[i]);

    return *max_element(begin(dp), end(dp));
  }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Solution {
  public int maxSubArray(int[] nums) {
    // dp[i] := max sum subarray ending w/ i
    int[] dp = new int[nums.length];

    dp[0] = nums[0];
    for (int i = 1; i < nums.length; ++i)
      dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]);

    return Arrays.stream(dp).max().getAsInt();
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Solution:
  def maxSubArray(self, nums: List[int]) -> int:
    # dp[i] := max sum subarray ending w/ i
    dp = [0] * len(nums)

    dp[0] = nums[0]
    for i in range(1, len(nums)):
      dp[i] = max(nums[i], dp[i - 1] + nums[i])

    return max(dp)

Approach 2: $O(1)$ DP

  • Time: $O(n)$
  • Space: $O(1)$
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution {
 public:
  int maxSubArray(vector<int>& nums) {
    int ans = INT_MIN;
    int sum = 0;

    for (const int num : nums) {
      sum = max(num, sum + num);
      ans = max(ans, sum);
    }

    return ans;
  }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Solution {
  public int maxSubArray(int[] nums) {
    int ans = Integer.MIN_VALUE;
    int sum = 0;

    for (final int num : nums) {
      sum = Math.max(num, sum + num);
      ans = Math.max(ans, sum);
    }

    return ans;
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Solution:
  def maxSubArray(self, nums: List[int]) -> int:
    ans = -math.inf
    summ = 0

    for num in nums:
      summ = max(num, summ + num)
      ans = max(ans, summ)

    return ans

Approach 3: Divide and Conquer

  • Time: $O(n\log n)$
  • Space: $O(\log n)$
 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
struct T {
  int left;   // Sum of the subarray w/ max sum (starting from the first num)
  int right;  // Sum of the subarray w/ max sum (ending at the the last num)
  int mid;    // Sum of the subarray w/ max sum
  int sum;    // Sum of the whole array
};

class Solution {
 public:
  int maxSubArray(vector<int>& nums) {
    return divideAndConquer(nums, 0, nums.size() - 1).mid;
  }

 private:
  T divideAndConquer(const vector<int>& nums, int l, int r) {
    if (l == r)
      return {nums[l], nums[l], nums[l], nums[l]};

    const int m = (l + r) / 2;
    const T t1 = divideAndConquer(nums, l, m);
    const T t2 = divideAndConquer(nums, m + 1, r);

    const int left = max(t1.left, t1.sum + t2.left);
    const int right = max(t1.right + t2.sum, t2.right);
    const int mid = max({t1.right + t2.left, t1.mid, t2.mid});
    const int sum = t1.sum + t2.sum;
    return {left, right, mid, sum};
  }
};
 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
class Solution {
  public int maxSubArray(int[] nums) {
    return divideAndConquer(nums, 0, nums.length - 1).mid;
  }

  private T divideAndConquer(int[] nums, int l, int r) {
    if (l == r)
      return new T(nums[l], nums[l], nums[l], nums[l]);

    final int m = (l + r) / 2;
    final T t1 = divideAndConquer(nums, l, m);
    final T t2 = divideAndConquer(nums, m + 1, r);

    final int left = Math.max(t1.left, t1.sum + t2.left);
    final int right = Math.max(t1.right + t2.sum, t2.right);
    final int mid = Math.max(t1.right + t2.left, Math.max(t1.mid, t2.mid));
    final int sum = t1.sum + t2.sum;
    return new T(left, right, mid, sum);
  }

  private record T(int left,   // Sum of the subarray w/ max sum (starting from the first num)
                   int right,  // Sum of the subarray w/ max sum (ending at the the last num)
                   int mid,    // Sum of the subarray w/ max sum,
                   int sum) {} // Sum of the whole array
}
 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
from dataclasses import dataclass


@dataclass(frozen=True)
class T:
  left: int
  right: int
  mid: int
  summ: int


class Solution:
  def maxSubArray(self, nums: List[int]) -> int:
    def divideAndConquer(l: int, r: int) -> T:
      if l == r:
        return T(nums[l], nums[l], nums[l], nums[l])

      m = (l + r) // 2
      t1 = divideAndConquer(l, m)
      t2 = divideAndConquer(m + 1, r)

      left = max(t1.left, t1.summ + t2.left)
      right = max(t1.right + t2.summ, t2.right)
      mid = max(t1.right + t2.left, t1.mid, t2.mid)
      summ = t1.summ + t2.summ
      return T(left, right, mid, summ)

    return divideAndConquer(0, len(nums) - 1).mid