第三大的数
一、LeetCode题解
瞧一瞧~
- 博健的LeetCode题解:Gitbook版本传送门
- 博健的LeetCode题解:CSDN传送门
- 前端进阶笔记:Gitbook传送门
二、算法题
题目
给定一个非空数组,返回此数组中第三大的数。如果不存在,则返回数组中最大的数。要求算法时间复杂度必须是O(n)。
示例
输入 | 输出 | 解释 |
---|---|---|
[3, 2, 1] | 1 | 第三大的数是 1. |
[1, 2,] | 2 | 第三大的数不存在, 所以返回最大的数 2 . |
[2, 2, 3, 1] | 输出: 1 | 第三大且唯一出现的数。存在两个值为2的数,它们都排第二 |
最优思路应该是 => 小顶堆思想
- 维护一个长度为3的堆
- 保持这个堆最小的永远在顶端
- 新的元素如果大于堆顶元素,就替换掉堆顶元素,并重新调整为小顶堆
- 最后返回堆顶元素
解法一(去重、剥离)
var thirdMax = function(nums) {
var k = 3
var obj = {}, arr = []
if(nums.length < 3){
return Math.max(...nums)
}// 如果原数组长度小于3,则直接返回最大值
for(let i = 0; i < nums.length;i++){
if(!obj[nums[i]]){
obj[nums[i]] = 1
}
}
for(let key in obj){
arr.push(Number(key))
}// 两次for是为了去重,这里可以优化,但意义不大
if(arr.length < 3){
return Math.max(...arr)
}// 如果新数组长度小于3,则直接返回最大值
while (0 < --k) {
arr.splice(arr.indexOf(Math.max(...arr)), 1)
}// 如果边界值都不满足,则剥离两次最大的值,且返回当前的最大值(第三大值)
return Math.max(...arr)
};
解法二(去重、排序)
var thirdMax = function(nums) {
var arr = new Set(nums)
arr = [...arr]
arr.sort(newSort)
if(arr.length<3) return arr[0]
return arr[2]
};
var newSort = function(a, b){
return b - a
}
解法三(维护长度为3的数组)(已经接近最优思路了)
var thirdMax = function(nums) {
var brr = []
var arr = new Set(nums)
arr = [...arr]
if(arr.length < 3) return Math.max(...arr)
for(let i = 0; i < arr.length; i++){
if(brr.length < 3){
brr.push(arr[i])
}else{
let min = Math.min(...brr)
if(arr[i] > min){
brr.splice(brr.indexOf(min), 1)
brr.push(arr[i])
}
}
}
return Math.min(...brr)
};