2441. Largest Positive Integer That Exists With Its Negative
Problem Description
You are given an integer array nums
that contains no zeros. Your task is to find the largest positive integer k
where both k
and -k
exist in the array.
The problem asks you to identify pairs of opposite numbers (positive and negative) in the array and return the largest positive value among these pairs. If no such pair exists, return -1
.
For example:
- If
nums = [3, -3, 1, -1, 4]
, both3
and-3
exist, and both1
and-1
exist. The largest positive value is3
, so return3
. - If
nums = [1, 2, 3, 4]
, there are no negative counterparts for any positive numbers, so return-1
. - If
nums = [-1, -2, -3, 3]
, only3
and-3
form a valid pair, so return3
.
The solution uses a hash table approach by converting the array to a set for O(1)
lookup time. It then checks each element x
in the set to see if its negative counterpart -x
also exists. Among all valid pairs, it returns the maximum positive value, or -1
if no such pairs exist.
Intuition
The key insight is that we need to find pairs of numbers that are opposites of each other (like 3
and -3
). When looking for such pairs, a natural question arises: how can we efficiently check if the negative counterpart of a number exists in the array?
A brute force approach would involve checking every element against every other element, which would take O(n²)
time. However, we can optimize this by recognizing that we just need to answer a yes/no question: "Does -x
exist in the array for a given x
?"
This type of membership checking is perfectly suited for a hash table (or set in Python), which provides O(1)
lookup time. By first converting our array into a set, we can quickly check if any element's negative counterpart exists.
Once we have this efficient lookup structure, we can iterate through all elements and check if their negative counterparts exist. Since we want the largest positive integer k
, we need to track the maximum value among all valid pairs.
The elegant part of the solution is using Python's generator expression with max()
function: max((x for x in s if -x in s), default=-1)
. This automatically:
- Filters for only those elements
x
where-x
also exists in the set - Finds the maximum among these valid elements
- Returns
-1
if no such pairs exist (using thedefault
parameter)
This approach ensures we examine each element only once while maintaining optimal time complexity of O(n)
.
Learn more about Two Pointers and Sorting patterns.
Solution Approach
The solution uses a hash table-based approach to efficiently find the largest positive integer that has its negative counterpart in the array.
Step 1: Create a Hash Set
s = set(nums)
We convert the input array nums
into a set s
. This transformation serves two purposes:
- Removes any duplicate values (though duplicates don't affect our answer)
- Enables
O(1)
time complexity for checking if an element exists
Step 2: Find Maximum Valid Pair
return max((x for x in s if -x in s), default=-1)
This line does the heavy lifting through a generator expression:
for x in s
: Iterate through each unique element in the setif -x in s
: Check if the negative counterpart ofx
exists in the set- This generates all elements that have their opposite number in the array
max(...)
: Find the maximum value among these valid elementsdefault=-1
: If no valid pairs exist (empty generator), return-1
Why This Works:
- When we check
if -x in s
, we're identifying both positive and negative numbers that form valid pairs - For example, if we have
3
and-3
in the set:- When
x = 3
, we check if-3
exists (it does) - When
x = -3
, we check if3
exists (it does)
- When
- The
max()
function naturally returns the largest value, which will always be positive among valid pairs (since for any pair(k, -k)
, the positivek
is larger than-k
)
Time Complexity: O(n)
where n
is the length of the array
- Converting array to set:
O(n)
- Iterating through set and checking membership:
O(n)
Space Complexity: O(n)
for storing the set
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with nums = [-2, 5, -3, 2, 3, -5]
.
Step 1: Create a Hash Set
s = set([-2, 5, -3, 2, 3, -5])
# s = {-2, 5, -3, 2, 3, -5}
We convert the array into a set for O(1) lookup operations.
Step 2: Check Each Element for Its Negative Counterpart
Let's trace through the generator expression (x for x in s if -x in s)
:
x = -2
: Check if-(-2) = 2
is in set → YES ✓ (2 exists)x = 5
: Check if-5
is in set → YES ✓ (-5 exists)x = -3
: Check if-(-3) = 3
is in set → YES ✓ (3 exists)x = 2
: Check if-2
is in set → YES ✓ (-2 exists)x = 3
: Check if-3
is in set → YES ✓ (-3 exists)x = -5
: Check if-(-5) = 5
is in set → YES ✓ (5 exists)
The generator produces: -2, 5, -3, 2, 3, -5
Step 3: Find Maximum
max([-2, 5, -3, 2, 3, -5]) = 5
The function returns 5
, which is indeed the largest positive integer that has its negative counterpart in the array.
Verification: We can see that the valid pairs are:
- (2, -2) → largest positive is 2
- (3, -3) → largest positive is 3
- (5, -5) → largest positive is 5
Among these, 5 is the maximum, confirming our answer.
Solution Implementation
1class Solution:
2 def findMaxK(self, nums: List[int]) -> int:
3 """
4 Find the largest positive integer k such that both k and -k exist in the array.
5
6 Args:
7 nums: List of integers
8
9 Returns:
10 The largest positive integer k where both k and -k exist in nums,
11 or -1 if no such integer exists
12 """
13 # Convert the list to a set for O(1) lookup time
14 num_set = set(nums)
15
16 # Find the maximum value among all numbers that have their negative counterpart
17 # Generator expression iterates through the set and checks if negative exists
18 # default=-1 returns -1 when no valid pairs are found
19 max_k = max((num for num in num_set if -num in num_set), default=-1)
20
21 return max_k
22
1class Solution {
2 /**
3 * Finds the largest positive integer k such that both k and -k exist in the array.
4 * Returns -1 if no such integer exists.
5 *
6 * @param nums the input array of integers
7 * @return the largest positive integer k where both k and -k exist, or -1 if none found
8 */
9 public int findMaxK(int[] nums) {
10 // Initialize result to -1 (default when no valid k exists)
11 int maxK = -1;
12
13 // Store all unique numbers from the array in a HashSet for O(1) lookup
14 Set<Integer> uniqueNumbers = new HashSet<>();
15 for (int number : nums) {
16 uniqueNumbers.add(number);
17 }
18
19 // Iterate through each unique number to find valid pairs
20 for (int number : uniqueNumbers) {
21 // Check if the negative counterpart exists in the set
22 if (uniqueNumbers.contains(-number)) {
23 // Update maxK with the larger positive value
24 // This works for both positive and negative numbers since we want the largest k
25 maxK = Math.max(maxK, number);
26 }
27 }
28
29 return maxK;
30 }
31}
32
1class Solution {
2public:
3 int findMaxK(vector<int>& nums) {
4 // Create a hash set to store all unique numbers for O(1) lookup
5 unordered_set<int> numSet(nums.begin(), nums.end());
6
7 // Initialize result to -1 (default return value if no valid pair exists)
8 int maxValue = -1;
9
10 // Iterate through each unique number in the set
11 for (int num : numSet) {
12 // Check if the negative counterpart exists in the set
13 if (numSet.count(-num)) {
14 // Update the maximum value (this will keep the largest positive number)
15 maxValue = max(maxValue, num);
16 }
17 }
18
19 // Return the largest positive integer that has its negative counterpart
20 // or -1 if no such pair exists
21 return maxValue;
22 }
23};
24
1/**
2 * Finds the largest positive integer k such that both k and -k exist in the array.
3 * Returns -1 if no such integer exists.
4 *
5 * @param nums - The input array of integers
6 * @returns The largest positive integer k where both k and -k exist in nums, or -1
7 */
8function findMaxK(nums: number[]): number {
9 // Initialize result to -1 (default when no valid k exists)
10 let maxPositiveWithNegative: number = -1;
11
12 // Create a set from the array for O(1) lookup
13 const numSet: Set<number> = new Set<number>(nums);
14
15 // Iterate through each unique number in the set
16 for (const currentNum of numSet) {
17 // Check if the negative counterpart exists in the set
18 if (numSet.has(-currentNum)) {
19 // Update the maximum if current number is larger
20 maxPositiveWithNegative = Math.max(maxPositiveWithNegative, currentNum);
21 }
22 }
23
24 return maxPositiveWithNegative;
25}
26
Time and Space Complexity
Time Complexity: O(n)
The algorithm performs the following operations:
- Converting the list
nums
to a set:O(n)
wheren
is the length of the array - The generator expression
(x for x in s if -x in s)
iterates through each element in the set once:O(n)
iterations - For each element
x
, checking if-x in s
isO(1)
on average for set lookup - The
max()
function processes all elements from the generator:O(n)
Overall time complexity: O(n) + O(n) = O(n)
Space Complexity: O(n)
The algorithm uses:
- A set
s
to store all unique elements fromnums
:O(n)
in the worst case when all elements are unique - The generator expression creates an iterator but doesn't store all values at once, using
O(1)
additional space - The
max()
function usesO(1)
space to track the maximum value
Overall space complexity: O(n)
Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Incorrectly Filtering Only Positive Numbers
The Mistake: A common error is to only check positive numbers when looking for pairs, thinking that we only need to verify if their negative counterparts exist:
# INCORRECT approach
def findMaxK(self, nums: List[int]) -> int:
num_set = set(nums)
# Only checking positive numbers
positive_nums = [num for num in num_set if num > 0]
for num in sorted(positive_nums, reverse=True):
if -num in num_set:
return num
return -1
Why It's Wrong:
While this might seem logical since we want the "largest positive k", it adds unnecessary complexity and filtering. The original solution's beauty is that it checks ALL numbers (both positive and negative), and max()
naturally returns the positive value from each valid pair.
The Fix:
Trust the max()
function to handle both positive and negative values correctly. When both k
and -k
exist, max()
will always select k
(the positive one) over -k
.
Pitfall 2: Not Handling Edge Cases Properly
The Mistake: Forgetting to handle the case when no valid pairs exist, leading to a ValueError:
# INCORRECT - will raise ValueError on empty sequence
def findMaxK(self, nums: List[int]) -> int:
num_set = set(nums)
return max(num for num in num_set if -num in num_set) # Missing default parameter
Why It's Wrong:
When no valid pairs exist (e.g., nums = [1, 2, 3]
), the generator expression produces an empty sequence, causing max()
to raise a ValueError: max() arg is an empty sequence
.
The Fix:
Always include the default=-1
parameter in the max()
function to handle empty sequences gracefully:
return max((num for num in num_set if -num in num_set), default=-1)
Pitfall 3: Using List Comprehension Instead of Generator Expression
The Mistake: Using a list comprehension when a generator expression would be more efficient:
# Less efficient approach
def findMaxK(self, nums: List[int]) -> int:
num_set = set(nums)
# Creates entire list in memory
valid_pairs = [num for num in num_set if -num in num_set]
return max(valid_pairs) if valid_pairs else -1
Why It's Suboptimal: While this works correctly, it creates an entire list in memory containing all valid numbers before finding the maximum. This uses extra space unnecessarily.
The Fix: Use a generator expression (with parentheses) instead of a list comprehension (with square brackets). The generator expression is more memory-efficient as it yields values one at a time:
return max((num for num in num_set if -num in num_set), default=-1)
You are given an array of intervals where intervals[i] = [start_i, end_i]
represent the start and end of the ith
interval. You need to merge all overlapping intervals and return an array of the non-overlapping intervals that cover all the intervals in the input.
Recommended Readings
Tech Interview Pattern Two Pointers Introduction If you prefer videos here's a super quick introduction to Two Pointers div class responsive iframe iframe src https www youtube com embed xZ4AfXHQ1VQ title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture allowfullscreen iframe div Two pointers is a common interview
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Don’t Miss This!