力扣414.第三大的数

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

示例 1:

输入:[3, 2, 1]
输出:1
解释:第三大的数是 1 。

示例 2:

输入:[1, 2]
输出:2
解释:第三大的数不存在, 所以返回最大的数 2 。

示例 3:

输入:[2, 2, 3, 1]
输出:1
解释:注意,要求返回第三大的数,是指在所有不同数字中排第三大的数。
此例中存在两个值为 2 的数,它们都排第二。在所有不同数字中排第三大的数为 1 。

来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/third-maximum-number

思路一:

1.先直接对数组全部数据进行排序,可以采用:

Arrays.sort(nums);

2.排序后数组从小到大排列,最大值为数组最后一个元素。从后向前遍历数组,找到小于最大值的第一个数,它就是第二大数,剩下的数和第二大数比较,小于它的第一个数就是第三大数。

class Solution {
    public int thirdMax(int[] nums) {
        Arrays.sort(nums);
        int maxNum = nums[nums.length - 1];
        int secondMaxNumIndex = -1;

        for (int i=nums.length-2; i>=0; i--) 
        {
            if (secondMaxNumIndex != -1)
            {
                if(nums[i] < nums[secondMaxNumIndex])
                    return nums[i];
            }
            else
            {
                if(nums[i] < maxNum)
                    secondMaxNumIndex = i;
            }
        }

        return maxNum;
    }
}

问题:耗时较大,排序后只用到了一部分数据,剩余的排好序的数据被抛弃,效率低。

思路二:

1.另建一个新的长度为3的数组,用来保存最大的三个不等的数。

2.以nums数组第一个元素为最大值,使用简单选择排序算法。选出最大的不同的三个数放入新数组。选够3个即可方法返回,否则返回最大值。

class Solution {
    public int thirdMax(int[] nums) {
        int[] maxThreeNum = new int[3];   
        int certainNumSum = 0;
        int maxNumIndex; 

        for(int i=0; i<nums.length; i++)
        {
            int temp;
            maxNumIndex=i;
            for(int j=i+1; j<nums.length; j++)
            {
                if(nums[j] > nums[maxNumIndex])
                {
                    maxNumIndex=j;
                }
            }

            temp = nums[i];
            nums[i] = nums[maxNumIndex];
            nums[maxNumIndex] = temp;

            if(certainNumSum==0 || nums[i]!=maxThreeNum[certainNumSum-1])
                maxThreeNum[certainNumSum++]=nums[i];

            if(certainNumSum==3) 
                return maxThreeNum[2];
        }

        return maxThreeNum[0];
    }
}

问题:时间耗时减少,但时间复杂度为O(n2),效率较低。

思路三:

1.另建一个新的长度为3的数组,用来保存最大的三个不等的数。

2.遍历数组,每次得到的一个元素都要和新数组的三个元素进行比较。相当于对这四个数进行排序,最小值被覆盖。遍历一遍就能得到最大的三个数。

class Solution {
    public int thirdMax(int[] nums) {
        long[] maxThreeNum = {Long.MIN_VALUE, Long.MIN_VALUE, Long.MIN_VALUE};   

        for(int i=0; i<nums.length; i++)
        {
            if(nums[i] > maxThreeNum[0])
            {
                maxThreeNum[2] = maxThreeNum[1];
                maxThreeNum[1] = maxThreeNum[0];
                maxThreeNum[0] = nums[i];
            }
            else if(nums[i] < maxThreeNum[0] && nums[i] > maxThreeNum[1])
            {
                maxThreeNum[2] = maxThreeNum[1];
                maxThreeNum[1] = nums[i];
            }
            else if(nums[i] < maxThreeNum[1] && nums[i] > maxThreeNum[2])
            {
                maxThreeNum[2] = nums[i];
            }
        }

        if(maxThreeNum[2] == Long.MIN_VALUE)
            return (int)maxThreeNum[0];
        else
            return (int)maxThreeNum[2];
    }
}

注意:

1.数组元素初始化值不能为Interger.MIN_VALUE,因为nums数组元素可取此值,最好初始化为Long.MIN_VALUE,最终返回时还要转为int

改进:

仍不是最优解,最后发现将数组拆开,写成3个长整型就行了。

class Solution {
    public int thirdMax(int[] nums) {
        long max = Long.MIN_VALUE;
        long min = Long.MIN_VALUE;
        long second = Long.MIN_VALUE;

        for(int i=0; i<nums.length; i++)
        {
            if(nums[i] > max)
            {
                min = second;
                second = max;
                max = nums[i];
            }
            else if(nums[i]<max && nums[i]>second)
            {
                min = second;
                second = nums[i];
            }
            else if(nums[i]<second && nums[i]>min)
            {
                min = nums[i];
            }
        }

        if(min == Long.MIN_VALUE)
            return (int)max;
        else
            return (int)min;
    }
}

 

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值