Swift - LeetCode - 第三大的数

487 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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!
    }
}

复杂度分析

  • 时间复杂度:O(nlogn)O(n\log n),其中 nn 是数组 nums\textit{nums} 的长度。排序需要 O(nlogn)O(n\log n) 的时间。

  • 空间复杂度:O(nlogn)O(n\log n)。排序需要的栈空间为 O(logn)O(\log n)

方法二:一次遍历

思路及解法

我们可以遍历数组,并用三个变量 aabbcc 来维护数组中的最大值、次大值和第三大值,以模拟方法二中的插入和删除操作。为方便编程实现,我们将其均初始化为小于数组最小值的元素,视作「无穷小」,比如 263-2^{63} 等。

遍历数组,对于数组中的元素 num\textit{num}

  • num>a\textit{num}>a,我们将 cc 替换为 bbbb 替换为 aaaa 替换为 num\textit{num},这模拟了将 num\textit{num} 插入有序集合,并删除有序集合中的最小值的过程;
  • a>num>ba>\textit{num}>b,类似地,我们将 cc 替换为 bbbb 替换为 num\textit{num}aa 保持不变;
  • b>num>cb>\textit{num}>c,类似地,我们将 cc 替换为 num\textit{num}aabb 保持不变;
  • 其余情况不做处理。

遍历结束后,若 cc 仍然为263 -2^{63},则说明数组中不存在三个或三个以上的不同元素,即第三大的数不存在,返回 aa,否则返回 cc

代码

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
    }
}

复杂度分析

  • 时间复杂度:O(n)O(n),其中 nn 是数组 nums\textit{nums} 的长度。

  • 空间复杂度:O(1)O(1)