一、数组_数组的遍历_414. 第三大的数

题目描述
给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。

示例 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值