Question

Formatted question description: https://leetcode.ca/all/53.html

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [−2,1,−3,4,−1,2,1,−5,4],
the contiguous subarray [4,−1,2,1] has the largest sum = 6.

More practice:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

@tag-array

Algorithm

The O(n) solution is to define two variables res and curSum, where res holds the final result to be returned, that is, the sum of the largest sub-array.

The initial value of curSum is 0, and each traversal of a number num, compare curSum + num and num. Store the larger value in curSum, and then store the larger value in res and curSum in res, and so on until the entire array is traversed, and the value of the largest sub-array can be obtained in res.

Code

Java

public class Maximum_Subarray {

	// o(N)
	public class Solution_oN {
		public int maxSubArray(int[] nums) {
			int res = Integer.MIN_VALUE, curSum = 0;
			for (int num : nums) {
				// like a 1D dp[i], 'curSum' is max sum up to index-i
				// if 'curSum' is <0 , then it will be num
				curSum = Math.max(curSum + num, num);
				res = Math.max(res, curSum);
			}
			return res;
		}
	}

	public class Solution {
		public int maxSubArray(int[] nums) {

			if (nums == null || nums.length == 0) {
				return 0;
			}

			// consider input: [-1,-2,-3], and [-3,-2,-1]
			int max = nums[0];

			int tmpSum = nums[0]; // @note: cannot set to 0
			for (int i = 1; i < nums.length; i++) {
				if (tmpSum < 0) { // even if current number is large positive on, this tmpSum makes no contribution
					tmpSum = nums[i];
				} else {
					tmpSum += nums[i];
				}

				max = Math.max(max, tmpSum);

			}

			return max;
		}

	}

	public class Solution_divide_conquer {

		/* O(n logn), still better than brute force O(n^2)

		Time analysis:

		1. Find-Max-Cross-Subarray: O(n) time
		2. Two recursive calls on input size n/2

		Thus:
			T(n) = 2T(n/2) + O(n)
			T(n) = O(n log n)

		*/
		public int maxSubArray(int[] nums) {

			if (nums == null || nums.length == 0) {
				return 0;
			}

			return dfs(nums, 0, nums.length - 1);
		}

		private int dfs(int[] nums, int start, int end) {

			if (start == end) {
				return nums[start];
			}

			int mid = (start + end) >> 1; // @note: possible overflow

			int left = dfs(nums, start, mid);
			int right = dfs(nums, mid + 1, end);

			int leftHalf = 0, rightHalf = 0;

			int leftMax = Integer.MIN_VALUE;
			int rightMax = Integer.MIN_VALUE;

			for (int i = mid + 1; i <= end; i++) {
				rightHalf += nums[i];
				rightMax = Math.max(rightHalf, rightMax);
			}

			for (int i = mid; i >= start; i--) {
				leftHalf += nums[i];
				leftMax = Math.max(leftMax, leftHalf);
			}

			return Math.max(rightMax + leftMax, Math.max(left, right));
		}
	}

}

All Problems

All Solutions