一、问题描述
给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。
二、示例及约束
示例 1:
输入: [3, 2, 1]
输出: 1
解释: 第三大的数是 1 。
示例 2:
输入: [1, 2]
输出: 2
解释: 第三大的数不存在, 所以返回最大的数 2 。
示例 3:
输入: [2, 2, 3, 1]
输出: 1
解释: 注意,要求返回第三大的数,是指在所有不同数字中排第三大的数。
此例中存在两个值为 2 的数,它们都排第二。在所有不同数字中排第三大的数为 1 。
提示:
● 1 <= nums.length <=
1
0
4
10^4
104
● -
2
31
2^{31}
231 <= nums[i] <=
2
31
2^{31}
231-1
三、代码
方法一:依次比较
class Solution {
public:
int thirdMax(vector<int>& nums) {
long first = LONG_MIN,second = LONG_MIN,third = LONG_MIN;
//将其赋为最小值,避免在后续比较时出现初始值比数组中值要大的情况
//注意:不能用INT_MIN,因为测试用例范围的最小值正好等于INT_MIN,因此取LONG_MIN
for(int i = 0;i < nums.size();i++){
if(first < nums[i]){
//如果最大值比某个值小,则将那个值赋给最大值
first = nums[i];
}
}
for(int j = 0;j < nums.size();j++){
if(nums[j] < first && second < nums[j]){
//如果第二大值除最大值以外,比某个值小,则将那个值赋给最二大值
second = nums[j];
}
}
for(int k = 0;k < nums.size();k++){
if(nums[k] < second && third < nums[k]){
//如果第三大值除最二大值以外,比某个值小,则将那个值赋给最三大值
third = nums[k];
}
}
if(third == LONG_MIN){
//如果没有找到第三大值,返回最大值
return first;
}else{
//如果找到第三大值,返回最三大值
return third;
}
}
};
方法二:一次遍历
class Solution {
public:
int thirdMax(vector<int>& nums) {
int *first = nullptr,*second = nullptr,*third = nullptr;
//定义为空指针,避免初始化时的数与数组进行比较时发生问题
for(int &num : nums){
//定义int类型的num
//增强for循环用法,在循环中将nums的值赋给num
//&表示引用,即赋值时同时改变原来的nums,如果不用&则表示复制了一个副本,原来的nums并没有进行改变
/*注意:如果不用&,这里会报错,因为如果改为int num : nums,那么num将是
一个整数值的副本,而不是引用。在这种情况下,后续代码块中的&num将会得到这
个副本的地址,而不是原始向量中元素的地址。由于这个副本在每次循环迭代结束
时都会被销毁,所以这些指针最终会指向无效的内存。*/
if(first == nullptr || num > *first){
//注意:首先判断该指针是否为空再进行比较,后续代码同理
//在迭代中,将新得到的最大值给first,其余的按照顺序往后排
third = second;
second = first;
first = #
//在迭代中,取num的地址,这样引用后就是数组中的值,后续代码同理
}else if((second == nullptr || *second < num) && num < *first){
//注意:这里不用判断first是否为空指针,因为first必然存在
//在迭代中,将新得到的最二大值给second,其余的按照顺序往后排
third = second;
second = #
}else if(second != nullptr && (third == nullptr || *third < num) && num < *second){
//注意:这里需要判断second是否为空指针,因为second不一定存在
//在迭代中,将新得到的最三大值给third
third = #
}
}
return third == nullptr ? *first : *third;
//如果third不为空指针,返回third,否则返回first
}
};
四、总结
时间复杂度:
方法一为O(n),其中 n 是数组 nums 的长度。
方法二为O(n),只需要遍历1次即可,因此总时间复杂度为 O(n)。
空间复杂度:O(1)。
方法 | 时间复杂度 | 空间复杂度 |
---|---|---|
方法一 | O( n n n) | O(1) |
方法二 | O( n n n) | O(1) |