0%

Leetcode 414 Third Maximum Number

Given a non-empty array of integers, return the third maximum number in this array. If it does not exist, return the maximum number. The time complexity must be in O(n).

Example 1:

1
2
3
4
5
Input: [3, 2, 1]

Output: 1

Explanation: The third maximum is 1.

Example 2:

1
2
3
4
5
Input: [1, 2]

Output: 2

Explanation: The third maximum does not exist, so the maximum (2) is returned instead.

Example 3:

1
2
3
4
5
6
Input: [2, 2, 3, 1]

Output: 1

Explanation: Note that the third maximum here means the third maximum distinct number.
Both numbers with value 2 are both considered as second maximum.

优先队列

这个题思路很简单,但是有坑的地方

首先说思路,求第k大的数通常是构造k个元素的优先队列,这里由于优先队列里的元素不能重复, 所以手动用vector构造.

  • 第1步创建一个3个元素的优先队列, 并且都赋值为INT_MIN. 这时vector为递增排列
  • 第2步 对于每个元素nums[i], 和vector最前面的元素vector[0]比较,如果大于这个元素,并且和后两个元素不重复,就将vector[0] 替换为nums[i], 同时排序vector
  • 第3步 当遍历完nums[i]时,vector[0]即为第3大的元素。注意如果vector[0] 为INT_MIN,那么说明没有第三大的元素 e.g. {2,2,2,2,4,4}, 这时根据题意要返回最大的元素vector[2].

这个思路的复杂度低O(n), 也只需要常数的空间复杂度。

但是,这个题坑的地方是,给的测试数组中包含INT_MIN = -2147483648 !!!**,上面的用INT_min作为最小值的策略就失效了。([1,2,-2147483648]**这样的数组不会得出正确结果 -2147483648)

所以,就要设置一个新的值表示所有的int的最小值,和-2147483648区分开。

有的做法为将int转换为long long,在设置 long long LONG_MIN = (long long)INT_MIN - 1,这是一种解决方法

我使用的方法是创建类型

1
pair<int,bool> real_min {INT_MIN, false}

数组中的值nums[i]定义为

1
pair<int,bool> fake {nums[i], false}

并重新定义大小关系 {INT_MIN, false} < {INT_MIN, true}。 这样即使nums中有INT_MIN也能正确区分是真的最小值还是只是-2147483648了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class Solution {
public:
int thirdMax(vector<int>& nums) {
if(nums.size() == 1)
return nums[0];
if(nums.size() == 2)
return max(nums[0],nums[1]);
pair<int,bool> pr = {INT_MIN, false};
vector<pair<int,bool>> top3(3,pr);
for(int i = 0; i < nums.size(); ++i)
{
pair<int,bool> tmp = {nums[i],true};
if(cmp_pair(tmp,top3[0]) > 0 && cmp_pair(tmp,top3[1]) != 0 && cmp_pair(tmp,top3[2]) != 0)
{
top3[0] = tmp;
sort(top3.begin(), top3.end(), cmp);
cout<<"i="<<i<<endl;
cout<<top3[0].first<<" "<<top3[1].first<<" "<<top3[2].first<<" "<<endl;
cout<<top3[0].second<<" "<<top3[1].second<<" "<<top3[2].second<<" "<<endl;
}
}
if(top3[0] == pr)
return top3[2].first;
return top3[0].first;
}
private:
int cmp_pair(const pair<int,bool>& a, const pair<int,bool>& b)
{
if(a.first != b.first)
{
return a.first > b.first ? 1 : -1;
}
else
{
if(a.second == false && b.second == true)
return -1;
if(a.second == true && b.second ==false)
return 1;
}
return 0;
}
static bool cmp(const pair<int,bool>& a, const pair<int,bool>& b)
{
if(a.first != b.first)
return a.first < b.first;
else
{
return (a.second == false) && (b.second ==true);
}

}
};