题目来源
题目描述
题目解析
排序
将数组从大到小排序后,从头开始遍历数组,通过判断相邻元素是否不同,来统计不同元素的个数。如果能找到三个不同的元素,就返回第三大的元素,否则返回最大的元素
class Solution {
public:
int thirdMax(vector<int>& nums) {
std::sort(nums.begin(), nums.end(), greater<>());
for(int i = 1, diff = 1; i < nums.size(); i++){
if(nums[i - 1] != nums[i] && (++diff == 3) ){
return nums[i];
}
}
return nums[0];
}
};
有序集合
我们可以遍历元素,同时用一个有序集合来维护数组中前三大的数。具体做法是每遍历一个数,就将其插入有序集合,如果有序集合的大小超过,就删除集合中的最小元素。这样可以保证有序集合的大小至多为,而且遍历结束后,如果有序集合的大小为3,其最小值就是数组中第三大的数;如果有序集合的大小不足3,那么就返回有序集合中的最大值
class Solution {
public:
int thirdMax(vector<int>& nums) {
std::set<int> set;
for(int num : nums){
set.insert(num);
if(set.size() > 3){
set.erase(set.begin());
}
}
return set.size() == 3 ? *set.begin() : *set.rbegin();
}
};
一次遍历
我们可以遍历数组,并用三个变量a、b、c来维护数组中的最大值,次大值和第三大值,以模拟方法二中的插入和删除操作。为方便编程实现,我们将其均初始化为小于数组最小值的元素,视作「无穷小」,比如 − 2 63 -2^{63} −263等。
遍历数组 ,对于数组中的元素num:
- 如果 n u m > a num > a num>a,我们将c替换为b,b替换为a,a替换为num。这就模拟了将num插入有序集合,并删除有序集合中的最小值的过程
- 如果 a > n u m > b a > num > b a>num>b,我们将c替换为b,b替换为num,a不变
- 若 b > n u m > b c b> num > bc b>num>bc,类似地,我们将 c替换为 um,a和 b保持不变;
如果遍历结束后,c仍然为【无穷小】,则说明数组中不存在三个或者是三个以上的不同元素,即第三大的数不存在,返回a,否则返回c
int thirdMax(vector<int>& nums) {
long a = std::numeric_limits<long>::min() , b = std::numeric_limits<long>::min(), c = std::numeric_limits<long>::min();
for(auto n : nums){
if(n > a){
c = b;
b = a;
a = n;
}else if(a > n && n > b){
c = b;
b = n;
}else if(b > n && n > c){
c = n;
}
}
return c == std::numeric_limits<long>::min() ? a : c;
}