Given a non-empty array of integers called nums
, your task is to return the third distinct maximum number in this array. If the third maximum does not exist, return the maximum number instead.
nums
may appear more than once, but only distinct values are considered for the "third maximum".Key Constraints:
When facing this problem, the first idea might be to sort the array and pick the third largest value. However, since duplicates do not count as distinct maximums, simply sorting and picking the third element from the end could be incorrect if there are repeated numbers.
To handle duplicates, we need a way to keep track of only unique values. This suggests using a data structure that automatically ignores duplicates, such as a set. After collecting all unique numbers, we can sort or otherwise determine the top three.
To optimize, we can avoid sorting the entire array by keeping track of the top three unique values as we iterate. This way, we don't waste time sorting values we don't need.
Let's break down the optimized approach step by step:
first
, second
, and third
) to store the highest, second highest, and third highest unique numbers seen so far.
first
, shift all values down and set first
to this number.first
and second
, update second
and shift third
down.second
and third
, update third
.third
was updated (i.e., we found three distinct maximums), return it. Otherwise, return first
(the maximum).
This approach ensures we only keep track of what matters and never waste time sorting the entire list.
Let's consider the input nums = [2, 2, 3, 1]
.
first = None
, second = None
, third = None
2
→ first = 2
2
(duplicate) → ignore3
→ first = 3
, second = 2
1
→ third = 1
first = 3
, second = 2
, third = 1
. All three are filled, so we return 1
(the third maximum).
If the input was [1, 2]
, after processing we'd have first = 2
, second = 1
, but third
would still be None
. Thus, we'd return 2
(the maximum).
Brute-force Approach:
O(n \log n)
O(n)
for storing unique elements.O(n)
O(n)
for the set (if using a set for uniqueness).The optimized approach is faster because it avoids sorting and only keeps track of the top three unique maximums.
The key to solving the "Third Maximum Number" problem efficiently is to focus only on unique values and keep track of just the top three as we iterate. By using a set to filter duplicates and carefully updating our three maximum variables, we avoid unnecessary computation and achieve optimal performance. This elegant approach demonstrates the power of combining simple data structures with thoughtful iteration.
class Solution:
def thirdMax(self, nums):
first = second = third = None
for num in nums:
if num == first or num == second or num == third:
continue
if first is None or num > first:
third = second
second = first
first = num
elif second is None or num > second:
third = second
second = num
elif third is None or num > third:
third = num
return third if third is not None else first
class Solution {
public:
int thirdMax(vector<int>& nums) {
long first = LONG_MIN, second = LONG_MIN, third = LONG_MIN;
for (int num : nums) {
if (num == first || num == second || num == third) continue;
if (num > first) {
third = second;
second = first;
first = num;
} else if (num > second) {
third = second;
second = num;
} else if (num > third) {
third = num;
}
}
return third == LONG_MIN ? first : third;
}
};
class Solution {
public int thirdMax(int[] nums) {
Long first = null, second = null, third = null;
for (int num : nums) {
if ((first != null && num == first) ||
(second != null && num == second) ||
(third != null && num == third)) {
continue;
}
if (first == null || num > first) {
third = second;
second = first;
first = (long) num;
} else if (second == null || num > second) {
third = second;
second = (long) num;
} else if (third == null || num > third) {
third = (long) num;
}
}
return third == null ? first.intValue() : third.intValue();
}
}
var thirdMax = function(nums) {
let first = null, second = null, third = null;
for (let num of nums) {
if (num === first || num === second || num === third) continue;
if (first === null || num > first) {
third = second;
second = first;
first = num;
} else if (second === null || num > second) {
third = second;
second = num;
} else if (third === null || num > third) {
third = num;
}
}
return third === null ? first : third;
};