Given a circular integer array nums
of length n
, return the maximum possible sum of a non-empty subarray of nums
. A circular array means the end of the array connects to the beginning of the array. A subarray may only include each element of the fixed buffer nums
at most once.
For example:
nums = [1,-2,3,-2]
should return 3
because the subarray [3]
has the maximum sum 3
.nums = [5,-3,5]
should return 10
because the subarray [5,5]
has the maximum sum 5 + 5 = 10
.nums = [-3,-2,-3]
should return -2
because the subarray [-2]
has the maximum sum -2
.Can you provide an efficient algorithm to solve this problem?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The problem asks us to find the largest sum from a consecutive section of numbers, where the beginning and end of the list are considered touching. The brute force way means we are going to try every possible section and see which one has the biggest sum.
Here's how the algorithm would work step-by-step:
def max_sub_array_circular_brute_force(numbers):
max_sum = float('-inf')
list_length = len(numbers)
# Check all possible regular subarrays
for start_index in range(list_length):
current_sum = 0
for end_index in range(start_index, list_length):
current_sum += numbers[end_index]
max_sum = max(max_sum, current_sum)
# Now check all possible circular subarrays
for start_index in range(list_length):
current_sum = 0
# Iterate through circular combinations
for section_length in range(1, list_length):
# This handles the wrap-around
current_index = (start_index + section_length) % list_length
current_sum += numbers[current_index]
max_sum = max(max_sum, current_sum)
# Account for the edge case, all negatives
if max_sum == float('-inf'):
max_sum = max(numbers)
return max_sum
The problem asks for the largest possible sum from a continuous part of a list, where the list can 'wrap around'. Instead of checking every possible part, we find both the largest regular sum and the smallest regular sum, then cleverly combine them.
Here's how the algorithm would work step-by-step:
def max_sub_array_circular(numbers):
def kadane_algorithm(nums):
current_max = 0
maximum_so_far = float('-inf')
for number in nums:
current_max = max(number, current_max + number)
maximum_so_far = max(maximum_so_far, current_max)
return maximum_so_far
# Find the maximum sum in a regular subarray.
max_sub_array_sum = kadane_algorithm(numbers)
inverted_numbers = [-number for number in numbers]
# Find the max sum of inverted array
max_sum_inverted_array = kadane_algorithm(inverted_numbers)
# Convert to smallest sum
min_sub_array_sum = -max_sum_inverted_array
total_array_sum = sum(numbers)
# Calculate the max circular sum
max_circular_sub_array_sum = total_array_sum - min_sub_array_sum
# Compare the two maximum sums.
return max(max_sub_array_sum, max_circular_sub_array_sum)
Case | How to Handle |
---|---|
Null or empty input array | Return 0 immediately as there are no subarrays to sum. |
Array with a single element | Return the single element as it's the only possible subarray. |
Array with all negative numbers | Return the largest negative number (least negative) as the maximum subarray sum in this case, which can be found during the min sum calculation. |
Array with all zeros | Return 0 as the maximum subarray sum. |
Integer overflow when summing large numbers | Use a larger data type like long to store the sum to prevent overflow. |
Array with a very large positive number and a few very large negative numbers | Kadane's algorithm correctly finds the maximum sum subarray, even with large positive and negative values. |
Array where the maximum subarray is the entire array | Kadane's algorithm and the circular sum logic will handle this case correctly, either with the standard max sum or total - min sum being the full array's sum. |
Array where the maximum circular subarray wraps around the end and the beginning | Calculate both the standard max subarray sum and the maximum circular subarray sum (total - min subarray sum) and return the larger of the two. |