题目描述
给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。
示例 1:
输入:[3, 2, 1]
输出:1
解释:第三大的数是 1 。
示例 2:
输入:[1, 2]
输出:2
解释:第三大的数不存在, 所以返回最大的数 2 。
示例 3:
输入:[2, 2, 3, 1]
输出:1
解释:注意,要求返回第三大的数,是指在所有不同数字中排第三大的数。
此例中存在两个值为 2 的数,它们都排第二。在所有不同数字中排第三大的数为 1 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/third-maximum-number
排序
1.将原有数组排序,并且找到第三个元素
2.这里第三个元素是不同的,利用相邻元素不同的特点来完成。
有序集合
1.首先保持一个有序的数组,数组的大小为3,这里若是超过3个,剩下的元素就删除
2.新的元素采取插入的方式,将其插入到有序数组中
3.这个好处是,若要求找到第i大的数字,可以很灵活的变动程序,相对容错机制好些
遍历数组,记录和比较法
1.首先通过三个变量保存最大,次大,第三大的数,初始化为int_min
2.思路是更新当前的最大值,次大,第三大的值,在去继续更新受影响的那些
3.而且在这个过程中还要保证,不能重复
4.最后,若是第三大的值存在则返回,否则返回最大值
缺点与不足:
1.我写很多代码的时候,都会有的一个缺点是不把思路想清楚了,就开始写,或者有的地方没想到
2.这版我花了10分钟写完了,但是一开始运行有很多示例通不过,之后,我就开始东补西凑的开始写,这个过程花了30多分钟,才险些通过
这次还算运气好的,其他运气不好的时候,怎么补,都不能通过所有的示例
3.这版代码写的很不好,浪费了时间不说,效果也不行
int thirdMax(vector<int>& nums) {
int first_num = INT_MIN;
int second_num = INT_MIN;
int three_num = INT_MIN;
bool isFirst = false;
for(int i = 0; i < nums.size(); i++) {
if(nums[i] == INT_MIN) { //如果发现数组中存在INT_MIN的值,那么第三大值,就很有可能是INT_MIN
isFirst = true;
}
//这里看下是否大于最大值,否则是否大于第二大值,其次,是否大于第三大值
//若大于的话,每次要更新是否影响别的
if(nums[i] > first_num) {
three_num = second_num;
second_num = first_num;
first_num = nums[i];
} else if(nums[i] > second_num && nums[i] != first_num) {
three_num = second_num;
second_num = nums[i];
} else if(nums[i] > three_num && nums[i] != second_num && nums[i] != first_num) {
three_num = nums[i];
}
}
if(second_num == three_num) isFirst = false; //这一步是判断是否会有两个INT_MIN的情况,这种情况便是没有第三大的值
//cout << first_num << second_num << three_num;
return three_num != INT_MIN || isFirst ? three_num : first_num;
}
一次遍历优化
1.我们可以遍历数组,并用三个变量 a、b 和 c 来维护数组中的最大值、次大值和第三大值
2.这里要求a,b,c不能重复,所以若num>a,则首先c=b,b=a,a=num,按照顺序来进行
3.a>num>b,则c=b,b=num;
4.c>num>b,则c=num
5.这里也就有去重的功能,因为这是对abc限定了范围,也就相当于插入排序
6.上一个程序INT_MIN的最小值,这里使用LONG_MIN可以通过,因为有可能数组中存在最小值的情况,所以需要使用LONG_MIN
7.本机INT_MIN和LONG_MIN是相同的,可能还和处理器有关系,所以这里不过多研究
INT_MIN=-2147483648
LONG_MIN=-9223372036854775808
int thirdMax(vector<int> &nums) {
//这里防止nums数组中又很小的数,这样程序就判断不出来了
long a = LONG_MIN, b = LONG_MIN, c = LONG_MIN; //这里需要使用长整形变量
for(int i = 0; i < nums.size(); i++) {
if(nums[i] > a) { //这里保证不重复
c = b; //这个一定要有顺序,否则会被覆盖
b = a;
a = nums[i];
} else if(a > nums[i] && nums[i] > b) {
c = b;
b = nums[i];
} else if(b > nums[i] && nums[i] > c) {
c = nums[i];
}
}
return c == LONG_MIN ? a : c;
}
这里还有种类似的做法,排除范围的影响,使用空指针,这样不容易因为范围边缘的数字,导致程序判断不出来是否有值
int *a = nullptr,if (a == nullptr || num > *a),这里就需要建立指针变量,并且判断的时候,也需要加上指针的限制。
int main() {
vector<int> nums = { 1, 2 };
int result = thirdMax(nums);
cout << result << endl;
return 0;
}