问题描述:
从一个数组中找出第三大的数,如果没有第三大的数,则返回最大的数。如果有重复元素的情况如[1,2,2,3],应该返回1,即不考虑相同的元素值。
要求时间复杂度为为o(n)。
解决:
首先想到使用三个变量max1,max2,max3来保存最大,次大,第三大的数,均初始化为Integer.MIN_VALUE(也就是2^31-1)。通过遍历数组,如果数组长度大于等于3,max1.max2.max3的值均从MIN_VALUE变成了数组中的值,这种情况下return max3即可。如果数组长度为1或者2,那么肯定max1被赋值或者max1或max2被赋值,而max3仍然为MIN_VALUE。我们可以通过判断max3的值是否为MIN_VALUE来决定是返回max1还是max3。似乎这种做法很美好,但是在测试中发生了错误。
试想TestCase为[1, 2,MIN_VALUE]这种情况,此时max3 = MIN_VALUE(注意这个值是数组中的值而非初始化的值),按此前的逻辑max3等于MIN_VALUE返回max1,显然是不对的。所以,要想正确的实现功能,需要加逻辑来判断max3的值是来自于初始化还是数组。可以做,但是我在leetcode的讨论区里找到了一种更好的方法。
作者: yuxiaofei2016
public int thirdMax(int[] nums) {
if(nums == null || nums.length == 0)
return -1;
Integer max1 = null;
Integer max2 = null;
Integer max3 = null;
for(Integer n:nums) {
//值相同元素直接跳过
if(n.equals(max1) || n.equals(max2) || n.equals(max3))
continue;
if(max1 == null || n > max1) {
max3 = max2;
max2 = max1;
max1 = n;
} else if(max2 == null || n>max2){
max3 = max2;
max2 = n;
} else if(max3 == null || n>max3) {
max3 = n;
}
}
return max3==null?max1:max3;
}
这种做法,使用Integer类型,初始max1,max2,max3为null。这样的方式,我们最终是判断max3是否为null来决定返回max1还是max3。避免了类似于上述TestCase出现的问题。另外需要注意n.equals(max1)...不可以写成n==max1。对于Integer类,equals方法比较的是值是否相同,==用来比较两个对象的引用是否相同。