持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情
题目
给你一个非空数组,返回此数组中 第三大的数。如果不存在,则返回数组中最大的数。
示例 1:
- 输入:
[3, 2, 1]- 输出:
1- 解释: 第三大的数是 1。
示例 2:
- 输入:
[1, 2]- 输出:
2- 解释: 第三大的数不存在, 所以返回最大的数 2。
示例 3:
- 输入:
[2, 2, 3, 1]- 输出:
1- 解释: 注意,要求返回第三大的数,是指在所有不同数字中排第三大的数。 此例中存在两个值为 2 的数,它们都排第二。在所有不同数字中排第三大的数为 1。
方法一:排序
思路及解法
将数组从大到小排序后,从头开始遍历数组,通过判断相邻元素是否不同,来统计不同元素的个数。如果能找到三个不同的元素,就返回第三大的元素,否则返回最大的元素。
代码
class Solution {
func thirdMax(_ nums: [Int]) -> Int {
let nums: [Int] = nums.sorted()
var count: Int = nums.count - 1
var diff: Int = 1
while count >= 1 {
if nums[count] != nums[count - 1] {
diff += 1
}
count -= 1
if diff == 3 {
return nums[count]
}
}
return nums.last!
}
}
复杂度分析
-
时间复杂度:,其中 是数组 的长度。排序需要 的时间。
-
空间复杂度:。排序需要的栈空间为 。
方法二:一次遍历
思路及解法
我们可以遍历数组,并用三个变量 、 和 来维护数组中的最大值、次大值和第三大值,以模拟方法二中的插入和删除操作。为方便编程实现,我们将其均初始化为小于数组最小值的元素,视作「无穷小」,比如 等。
遍历数组,对于数组中的元素 :
- 若 ,我们将 替换为 , 替换为 , 替换为 ,这模拟了将 插入有序集合,并删除有序集合中的最小值的过程;
- 若 ,类似地,我们将 替换为 , 替换为 , 保持不变;
- 若 ,类似地,我们将 替换为 , 和 保持不变;
- 其余情况不做处理。
遍历结束后,若 仍然为,则说明数组中不存在三个或三个以上的不同元素,即第三大的数不存在,返回 ,否则返回 。
代码
class Solution {
func thirdMax(_ nums: [Int]) -> Int {
var a = Int.min
var b = Int.min
var c = Int.min
for num in nums {
if num > a {
c = b
b = a
a = num
} else if a > num && num > b {
c = b
b = num
} else if b > num && num > c {
c = num
}
}
return c == Int.min ? a : c
}
}
复杂度分析
-
时间复杂度:,其中 是数组 的长度。
-
空间复杂度:。