Given an integer array nums
, return the maximum possible sum of elements of the array such that it is divisible by three.
Example 1:
Input: nums = [3,6,5,1,8] Output: 18 Explanation: Pick numbers 3, 6, 1 and 8 their sum is 18 (maximum sum divisible by 3).
Example 2:
Input: nums = [4] Output: 0 Explanation: Since 4 is not divisible by 3, do not pick any number.
Example 3:
Input: nums = [1,2,3,4,4] Output: 12 Explanation: Pick numbers 1, 3, 4 and 4 their sum is 12 (maximum sum divisible by 3).
Constraints:
1 <= nums.length <= 4 * 104
1 <= nums[i] <= 104
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 core idea is to explore every single possible group of numbers. For each group, we check if the sum of the numbers is perfectly divisible by three. We then want to find the biggest sum we've seen so far that meets our criteria.
Here's how the algorithm would work step-by-step:
def greatest_sum_divisible_by_three_brute_force(numbers):
maximum_sum = 0
number_of_numbers = len(numbers)
# Iterate through all possible subsets of the input numbers
for i in range(1 << number_of_numbers):
current_subset = []
for j in range(number_of_numbers):
if (i >> j) & 1:
current_subset.append(numbers[j])
# Calculate the sum of the current subset
current_sum = sum(current_subset)
#Check if the current sum is divisible by 3
if current_sum % 3 == 0:
#Update maximum_sum if needed
maximum_sum = max(maximum_sum, current_sum)
return maximum_sum
The best way to solve this problem is to keep track of the smallest numbers that leave remainders of 1 and 2 when divided by 3. As we go through the numbers, we update these smallest values, and then use them to figure out if we can improve our total sum to be divisible by 3.
Here's how the algorithm would work step-by-step:
def greatest_sum_divisible_by_three(numbers):
total_sum = sum(numbers)
remainder = total_sum % 3
if remainder == 0:
return total_sum
smallest_remainder_one = float('inf')
second_smallest_remainder_one = float('inf')
smallest_remainder_two = float('inf')
second_smallest_remainder_two = float('inf')
for number in numbers:
if number % 3 == 1:
if number < smallest_remainder_one:
second_smallest_remainder_one = smallest_remainder_one
smallest_remainder_one = number
elif number < second_smallest_remainder_one:
second_smallest_remainder_one = number
elif number % 3 == 2:
if number < smallest_remainder_two:
second_smallest_remainder_two = smallest_remainder_two
smallest_remainder_two = number
elif number < second_smallest_remainder_two:
second_smallest_remainder_two = number
if remainder == 1:
# We need to subtract either one number with remainder 1,
# or two numbers with remainder 2.
option1 = total_sum - smallest_remainder_one
option2 = total_sum - (smallest_remainder_two + second_smallest_remainder_two)
# Handle edge cases where we don't have enough numbers.
if smallest_remainder_one == float('inf'):
option1 = float('-inf')
if smallest_remainder_two == float('inf') or second_smallest_remainder_two == float('inf'):
option2 = float('-inf')
return max(option1, option2) if max(option1, option2) > 0 else 0
else:
# We need to subtract either one number with remainder 2,
# or two numbers with remainder 1.
option1 = total_sum - smallest_remainder_two
option2 = total_sum - (smallest_remainder_one + second_smallest_remainder_one)
# Handle edge cases where we don't have enough numbers.
if smallest_remainder_two == float('inf'):
option1 = float('-inf')
if smallest_remainder_one == float('inf') or second_smallest_remainder_one == float('inf'):
option2 = float('-inf')
# Return the greater of the two sums
return max(option1, option2) if max(option1, option2) > 0 else 0
Case | How to Handle |
---|---|
Empty input array | Return 0 since no sum can be formed. |
Array with only one element | If the single element is divisible by 3, return it; otherwise, return 0. |
Array with all negative numbers | Find the largest sum of numbers divisible by 3, handling negative modulo appropriately. |
Array with all zeros | Return 0 since the greatest sum divisible by 3 is 0. |
Array with very large numbers that could lead to integer overflow | Use long data type to store the intermediate sums. |
Array where no combination of numbers sums to a multiple of 3 | Return 0, as there's no valid sum. |
Array with a mix of positive and negative numbers, with a large range | The dynamic programming approach correctly considers both positive and negative contributions to the remainders. |
Maximum array size causing memory issues | The constant space dynamic programming approach should handle large arrays without memory overflow. |