给你一个非空数组,返回此数组中第三大的数 。如果不存在,则返回数组中最大的数。
输入:[3, 2, 1]
输出:1
解释:第三大的数是 1 。
这个题力扣给的难度是简单。
一拿到题第一个想到的就是排序,不过很显然用排序的话效率会很低,题目建议将时间复杂度优化到O(n),不过还是先把题目写出来再去优化吧。
错误的算法思路:先判断这个数组有多长,如果小于3就另作判断,大于3就将其按递增排序后选择倒数第三个数字即为答案。
然而我又被锤了
这次是没读清楚题目的意思,题目要求返回的是第三大的数字,这个数组中是有可能有重复的数字的,所以直接返回倒数第三个数字是不靠谱的,而且就算数组长度大于3,也不一定是有第三大的数字的,所以上面的算法思路是有问题的,题目要求样例中也给出了这种情况,看来看题还是得仔细一点。
新的算法思路:先将数组进行排序,然后通过一个循环从数组最大的数开始遍历整个数组,设置一个标记变量,如果说当前数字和前一个数字不一样,标记变量就加1,如果一样就继续遍历,直到遍历完整个数组,如果标记变量仍然没有达到2,则说明该数组中没有第三大的数字,则直接返回数组最后一个元素(最大的元素)
源码部分:时间复杂度为O(nlgn)因为用到了快排,空间复杂度为O(1);
import static java.util.Arrays.sort;
class Solution {
public int thirdMax(int[] nums) {
int i;
int flag = 0;
sort(nums);
for (i = nums.length - 1; flag != 2; i--) {
//这里不是当i<0时,因为下面有i-1的下标,所以要设置为当i==0时退出
if(i == 0){
return nums[nums.length - 1];
}else{
if (nums[i] != nums[i - 1]) {
flag++;
}
}
}
return nums[i];
}
}
执行用时:
2 ms ,在所有 Java 提交中击败了46.66%的用户
内存消耗:
38.3 MB, 在所有 Java 提交中击败了52.80%的用户
在题解区看到有大佬有红黑树来写,咋自己就想不到呢,java中的这个题可以用TreeSet来实现呢。
思路一: 借用TreeSet(红黑树) O(n)
比较好想的思路
维护一个只有3个元素的TreeSet,如果大于三个元素就就把Set中的最小最小值remove掉。
最后如果Set中元素小于3就返回Set最大值,否则返回最小值。
时间复杂度: O(n * log3) == O(n)
作者:happy_yuxuan
思路二: 用三个变量来存放第一大,第二大,第三大的元素的变量,分别为one, two, three;
遍历数组,若该元素比one大则往后顺移一个元素,比two大则往往后顺移一个元素,比three大则赋值个three;
最后得到第三大的元素,若没有则返回第一大的元素。
作者:happy_yuxuan
待我将java集合复习完后再来更新这个TreeSet的算法