An interactive visualization of the divide and conquer approach for finding the contiguous subarray with the largest sum. Watch how the array is split, and how left, right, and crossing subarrays are compared at each recursion level.
Divide and Conquer LeetCode 53 ↗ Mediumnums, find the contiguous subarray (containing at least one number)
which has the largest sum and return its sum.[-2, 1, -3, 4, -1, 2, 1, -5, 4],
the contiguous subarray [4, -1, 2, 1] has the largest sum = 6.
fun maxSubArray(nums: IntArray, left: Int, right: Int): Int { if (left == right) { return nums[left] } val mid = (left + right) / 2 val leftMax = maxSubArray(nums, left, mid) val rightMax = maxSubArray(nums, mid + 1, right) val crossMax = maxCrossing(nums, left, mid, right) return maxOf(leftMax, rightMax, crossMax)}fun maxCrossing(nums: IntArray, left: Int, mid: Int, right: Int): Int { var leftSum = Int.MIN_VALUE var currSum = 0 for (i in mid downTo left) { currSum += nums[i] leftSum = maxOf(leftSum, currSum) } var rightSum = Int.MIN_VALUE currSum = 0 for (i in mid + 1..right) { currSum += nums[i] rightSum = maxOf(rightSum, currSum) } return leftSum + rightSum}
The maximum subarray must lie in exactly one of three places relative to the midpoint: entirely in the left half, entirely in the right half, or crossing the midpoint. By recursively solving the left and right halves, and computing the best crossing subarray, we compare all three candidates and return the maximum.
left == right, the subarray is a single element — return it.mid = (left + right) // 2 and recursively find the max subarray in nums[left..mid] and nums[mid+1..right].mid toward left, tracking the best sum. Then expand right from mid+1 toward right, tracking the best sum. The crossing max is the sum of these two best halves.max(left_max, right_max, cross_max).
At each of the O(log n) recursion levels, we do O(n) total work
computing crossing subarrays, giving O(n log n) overall.
The recursion stack uses O(log n) space.