Problem Description

Given a non-empty array, return the third largest number in the array. If it does not exist, returns the largest number in the array.

Example 1:

 输入:[3, 2, 1]
输出:1
解释:第三大的数是 1 。

Example 2:

 输入:[1, 2]
输出:2
解释:第三大的数不存在, 所以返回最大的数 2 。

Example 3:

 输入:[2, 2, 3, 1]
输出:1
解释:注意,要求返回第三大的数,是指在所有不同数字中排第三大的数。
此例中存在两个值为 2 的数,它们都排第二。在所有不同数字中排第三大的数为 1 。
Leetcode original title address: https://leetcode.cn/problems/third-maximum-number

solution

After the scheme is deduplicated and sorted, see if there is a third largest number

 var thirdMax = function (nums) {
    let n = [...new Set(nums)].sort(function (a, b) { // 1. 使用Set去重,并从大到小排列
        return b - a
    })
    if (n.length >= 3) { // 2. 操作完以后,如果还有3或多项,就直接取第三大的数返回即可
        return n[2]
    } else { // 3. 操作完以后,有可能只剩一个或者两个了,按照题意,那就直接返回最大的即可
        return n[0]
    }
};

Scheme 2 defines three -Infinity cyclic comparison and assignment

Before looking at the code below, we have to review two things

Knowledge Review 1: Swap the Values of Two Variables

The most common is to define a temporary variable temp as a transfer station for the exchange. For example, we want to exchange the values of a and b below.

 var a = 666;
var b = 777;
/* 定义临时变量temp中转站 */ 
var temp = null;
temp = a
a = b
b = temp

Of course, a better way is to not define variables and use 数组的解构特性 to do the exchange, for example:

 let a = 666;
let b = 777;
[a, b] = [b, a]
console.log(a, b); // 777 666

Why mention this?

Because the following code loop needs to compare the largest, second largest, and third largest values. 如果新值(循环中的项),比最大的还大,那么就把这个新值交换为最大,原来的最大,交换为第二大,原来的第二大,交换为第三大;

According to this rule, the size of the value is compared in a loop, and the value can be exchanged.

Knowledge Review 2: Infinity infinity, and -Infinity infinity

Infinity This seems to be not used much. If you use it, it is also in the CSS animation to let the animation run infinitely, for example:
animation: rotation 3s linear infinite;

But you need to brush algorithm questions (manual dog head)

Infinity 3110abd916ca45ffae52a5f45c6c06e0---是因为在初始状态下,我们需要定义三个变量: 最大第二大第三大的3 variables, in the subsequent loop, each item must be exchanged and compared, so only -Infinity can be used to define 3 initial variables.

The corresponding maximum and minimum numbers can also be represented by Number.MAX_VALUE and -Number.MAX_VALUE . In addition, there is a very good translation, please share: https://blog.fundebug.com/2019/12/23/infinity_in_js/

After reviewing these two knowledge points, and then look at the code, it is easy to understand

code

 var thirdMax = function (nums) {
    let biggest = -Infinity // 1. 定义最大数初始值为无穷小
    let secondLargest = -Infinity // 2. 定义第二大数初始值为无穷小
    let thirdLargest = -Infinity // 3. 定义第三大数初始值为无穷小
    for (let i = 0; i < nums.length; i++) { // 4. 遍历数组去比较大小
        if (nums[i] > biggest) { // 5. 如果新的数比最大值还要大,那么新的数当老大,原来的老大退居成老二了,原来的老二退居成老三了,原来的老三直接`退休了`
            [biggest, secondLargest, thirdLargest] = [nums[i], biggest, secondLargest]
        } else if (nums[i] == biggest) { // 6. 如果新的数和老大一样,那么就不交换了,因为相当于没变,就直接忽略之continue跳过,当然不加continue也是没问题的,加上效率高一些
            continue
        } else if (nums[i] > secondLargest) { // 7. 如果新的数比老二大,但是没有老大大,那么老大不用变、新的数当老二、原来的老二就被降级成老三了。原来的老三依旧直接退休了
            [biggest, secondLargest, thirdLargest] = [biggest, nums[i], secondLargest]
        } else if (nums[i] == secondLargest) { // 8. 这个同6. 一样。不赘述
            continue
        } else if (nums[i] > thirdLargest) { // 9. 如果新来的数,只比老三大一些,那么,老大、老二不用动。新来的数直接把原来的老三赶走,自己当老三就行喽
            [biggest, secondLargest, thirdLargest] = [biggest, secondLargest, nums[i]]
        }
    }
    // 10. 最后要判断一下,因为有可能找不到老三(比如数组只有两项,或者数组有很多项,但是都重复了,毕竟重复的会被忽略)
    if (thirdLargest === -Infinity) { // 11. 若老三还是初始状态,就说明没有老三(老三的位子空缺)
        return biggest // 12. 依照题意,返回老大
    } else {
        return thirdLargest // 13. 老三的位子有人做,那就返回老三
    }
};

From the above review knowledge points, you can get Infinity or use Number.MAX_VALUE instead, so the above code can be replaced with:

 var thirdMax = function (nums) {
    let biggest = -Number.MAX_VALUE
    let secondLargest = -Number.MAX_VALUE
    let thirdLargest = -Number.MAX_VALUE
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] > biggest) {
            [biggest, secondLargest, thirdLargest] = [nums[i], biggest, secondLargest]
        } else if (nums[i] == biggest) {
            continue
        } else if (nums[i] > secondLargest) {
            [biggest, secondLargest, thirdLargest] = [biggest, nums[i], secondLargest]
        } else if (nums[i] == secondLargest) {
            continue
        } else if (nums[i] > thirdLargest) {
            [biggest, secondLargest, thirdLargest] = [biggest, secondLargest, nums[i]]
        }
    }
    if (thirdLargest === -Number.MAX_VALUE) {
        return biggest
    } else {
        return thirdLargest
    }
};

Summarize

Well, take a look, and find that the time complexity of the second solution is indeed better. Of course, three variables are defined, so the space complexity is a little more. However, the overall idea is to change space for time ^_^


水冗水孚
1.1k 声望585 粉丝

每一个不曾起舞的日子,都是对生命的辜负