Max Pair Sum in an Array
EasyPrompt
You are given an integer array nums. You have to find the maximum sum of a pair of numbers from nums such that the largest digit in both numbers is equal.
For example, 2373 is made up of three distinct digits: 2, 3, and 7, where 7 is the largest among them.
Return the maximum sum or -1 if no such pair exists.
Example 1:
Input: nums = [112,131,411]
Output: -1
Explanation:
Each numbers largest digit in order is [2,3,4].
Example 2:
Input: nums = [2536,1613,3366,162]
Output: 5902
Explanation:
All the numbers have 6 as their largest digit, so the answer is 2536 + 3366 = 5902.
Example 3:
Input: nums = [51,71,17,24,42]
Output: 88
Explanation:
Each number's largest digit in order is [5,7,7,4,4].
So we have only two possible pairs, 71 + 17 = 88 and 24 + 42 = 66.
Constraints:
2 <= nums.length <= 1001 <= nums[i] <= 104
Approaches
3 approaches with complexity analysis and trade-offs.
This approach involves checking every possible pair of numbers in the array. For each pair, we determine if they share the same largest digit. If they do, we calculate their sum and update the maximum sum found so far. This method is straightforward but not the most efficient.
Algorithm
- Initialize a variable
maxSumto -1. - Create a helper function
getLargestDigit(int n)that returns the largest digit in a numbern. - Use a nested loop to iterate through every unique pair of numbers
(nums[i], nums[j])in the array. - For each pair, find the largest digit of
nums[i]andnums[j]. - If the largest digits are the same, calculate their sum.
- Update
maxSumwith the current pair's sum if it is greater than the existingmaxSum. - After checking all pairs, return
maxSum.
Walkthrough
The core idea is to use nested loops to generate all unique pairs (nums[i], nums[j]) where i < j. A helper function, getLargestDigit(n), is used to find the largest digit of any given number n. This function works by repeatedly taking the number modulo 10 to get the last digit and dividing by 10 to remove it, keeping track of the maximum digit seen. Inside the inner loop, we call this helper function for both nums[i] and nums[j]. If their largest digits are equal, we compute their sum and compare it with a running maximum, updating it if the new sum is larger. We initialize the maximum sum to -1, which is the value to be returned if no valid pair is found.
class Solution { private int getLargestDigit(int n) { int maxDigit = 0; String s = Integer.toString(n); for (char c : s.toCharArray()) { maxDigit = Math.max(maxDigit, c - '0'); } return maxDigit; } public int maxSum(int[] nums) { int n = nums.length; int maxSum = -1; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (getLargestDigit(nums[i]) == getLargestDigit(nums[j])) { maxSum = Math.max(maxSum, nums[i] + nums[j]); } } } return maxSum; }}Complexity
Time
O(N^2 * D), where N is the number of elements in `nums` and D is the maximum number of digits in a number. Since D is small and constant (at most 5 for numbers up to 10^4), the complexity is effectively O(N^2). We iterate through approximately N^2 / 2 pairs.
Space
O(1), as we only use a few variables to store the maximum sum and loop indices, regardless of the input size.
Trade-offs
Pros
Simple to understand and implement.
Uses constant extra space, O(1).
Cons
The time complexity is O(N^2), which is inefficient for large input arrays.
It performs redundant calculations for the largest digit of each number.
A more optimized approach is to group numbers by their largest digit. By doing this, we avoid redundant comparisons. We can use a hash map where keys are the largest digits (0-9) and values are lists of numbers that have that largest digit. After grouping, we find the pair with the maximum sum within each group.
Algorithm
- Create a hash map,
groups, where keys are digits (0-9) and values are lists of integers. - Iterate through the input array
nums. For each numbernum:- Find its largest digit
d. - Add
numto the list atgroups.get(d).
- Find its largest digit
- Initialize
maxSum = -1. - Iterate through each list in the
groupsmap's values. - If a list has two or more numbers, find the two largest numbers in that list.
- Calculate their sum and update
maxSumif this sum is greater. - Return
maxSum.
Walkthrough
First, we iterate through the input array nums once. For each number, we compute its largest digit. We then use a hash map (e.g., Map<Integer, List<Integer>>) to store these numbers. The largest digit serves as the key, and we add the number to the list associated with that key. After populating the map, we iterate through its values (the lists of numbers). For any list that contains two or more numbers, we know a valid pair can be formed. To find the maximum sum for a given group, we need the two largest numbers from its list. We can find these two numbers in a single pass through the list, which is more efficient than sorting the entire list. We keep track of the overall maximum sum found across all groups and return it.
import java.util.*; class Solution { private int getLargestDigit(int n) { int maxDigit = 0; while (n > 0) { maxDigit = Math.max(maxDigit, n % 10); n /= 10; } return maxDigit; } public int maxSum(int[] nums) { Map<Integer, List<Integer>> groups = new HashMap<>(); for (int num : nums) { int d = getLargestDigit(num); groups.computeIfAbsent(d, k -> new ArrayList<>()).add(num); } int maxSum = -1; for (List<Integer> list : groups.values()) { if (list.size() >= 2) { Collections.sort(list, Collections.reverseOrder()); maxSum = Math.max(maxSum, list.get(0) + list.get(1)); } } return maxSum; }}Complexity
Time
O(N log N) if sorting each group, or O(N*D) if finding the top two elements linearly. The provided code uses sorting, making it O(N log N) in the worst case where all numbers fall into one group. An O(N*D) or O(N) solution is possible by finding the top two elements in linear time for each group.
Space
O(N), as in the worst-case scenario, the hash map might need to store all N numbers from the input array.
Trade-offs
Pros
Significantly faster than the brute-force approach with linear time complexity.
Groups numbers logically, which can be a useful intermediate step for similar problems.
Cons
Requires extra space proportional to the input size to store the groups of numbers.
This is the most efficient approach, combining the logic into a single pass over the input array while using constant extra space. The idea is to keep track of the largest number seen so far for each possible largest digit (0-9).
Algorithm
- Initialize
maxSum = -1. - Initialize an integer array
maxForDigitof size 10 with all zeros. This array will store the largest number seen so far for each largest digit. - For each
numin the input arraynums:- Calculate its largest digit,
d. - If
maxForDigit[d]is not zero, it means we've seen a previous number with the same largest digit. We form a pair withnumandmaxForDigit[d]and updatemaxSum. - Update
maxForDigit[d]to be the maximum of its current value andnum.
- Calculate its largest digit,
- Return
maxSum.
Walkthrough
We use an array of size 10, say maxForDigit, to store the largest number encountered for each digit from 0 to 9. This array is initialized with zeros. We iterate through the input array nums just once. For each num, we first find its largest digit, d. Then, we check maxForDigit[d]. If it's greater than 0, it means we have already seen at least one number with the same largest digit d. The value maxForDigit[d] holds the largest of those previous numbers. We can form a pair (num, maxForDigit[d]) and update our global maxSum. Finally, regardless of whether a pair was formed, we update maxForDigit[d] with num if num is larger than the current value stored. This ensures that for any future number with largest digit d, it will be paired with the largest number seen so far. This method cleverly finds the maximum pair sum without needing to store all numbers, leading to optimal space complexity.
class Solution { private int getLargestDigit(int n) { int maxDigit = 0; while (n > 0) { maxDigit = Math.max(maxDigit, n % 10); n /= 10; } return maxDigit; } public int maxSum(int[] nums) { int maxSum = -1; int[] maxForDigit = new int[10]; for (int num : nums) { int d = getLargestDigit(num); if (maxForDigit[d] != 0) { maxSum = Math.max(maxSum, num + maxForDigit[d]); } maxForDigit[d] = Math.max(maxForDigit[d], num); } return maxSum; }}Complexity
Time
O(N * D), where N is the number of elements and D is the number of digits. We iterate through the array once, and for each element, we perform a constant number of operations plus the digit calculation. This simplifies to O(N) linear time.
Space
O(1). We only use an array of fixed size 10 to store the maximum numbers for each digit. The space requirement is constant and does not depend on the size of the input array.
Trade-offs
Pros
Optimal time complexity (linear).
Optimal space complexity (constant).
Requires only a single pass through the data.
Cons
The logic might be slightly less intuitive at first glance compared to the grouping approach.
Solutions
Solution
class Solution {public int maxSum(int[] nums) { int ans = -1; int n = nums.length; for (int i = 0; i < n; ++i) { for (int j = i + 1; j < n; ++j) { int v = nums[i] + nums[j]; if (ans < v && f(nums[i]) == f(nums[j])) { ans = v; } } } return ans; }private int f(int x) { int y = 0; for (; x > 0; x /= 10) { y = Math.max(y, x % 10); } return y; }}class Solution {public: int maxSum(vector<int> &nums) { int ans = -1; int n = nums.size(); auto f = [](int x) { int y = 0; for (; x; x /= 10) { y = max(y, x % 10); } return y; }; for (int i = 0; i < n; ++i) { for (int j = i + 1; j < n; ++j) { int v = nums[i] + nums[j]; if (ans < v && f(nums[i]) == f(nums[j])) { ans = v; } } } return ans; }};class Solution: def maxSum(self, nums: List[int]) -> int: ans = - 1 for i, x in enumerate(nums): for y in nums[i + 1:]: v = x + y if ans < v and max(str(x)) == max(str(y)): ans = v return ansVideo walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.