C#LeetCode刷题之#414-第三大的数(Third Maximum Number)

C#LeetCode刷题之#414-第三大的数(Third Maximum Number)

问题

给定一个非空数组,返回此数组中第三大的数。如果不存在,则返回数组中最大的数。要求算法时间复杂度必须是O(n)。

输入: [3, 2, 1]

输出: 1

解释: 第三大的数是 1.

输入: [1, 2]

输出: 2

解释: 第三大的数不存在, 所以返回最大的数 2 .

输入: [2, 2, 3, 1]

输出: 1

解释: 注意,要求返回第三大的数,是指第三大且唯一出现的数。
存在两个值为2的数,它们都排第二。

Given a non-empty array of integers, return the third maximum number in this array. If it does not exist, return the maximum number. The time complexity must be in O(n).

Input: [3, 2, 1]

Output: 1

Explanation: The third maximum is 1.

Input: [1, 2]

Output: 2

Explanation: The third maximum does not exist, so the maximum (2) is returned instead.

Input: [2, 2, 3, 1]

Output: 1

Explanation: Note that the third maximum here means the third maximum distinct number.
Both numbers with value 2 are both considered as second maximum.

示例

public class Program {

    public static void Main(string[] args) {
        int[] nums = null;

        nums = new int[] { 3, 2, 1 };
        var res = ThirdMax(nums);
        Console.WriteLine(res);

        nums = new int[] { 3, 2, 1 };
        res = ThirdMax2(nums);
        Console.WriteLine(res);

        Console.ReadKey();
    }

    private static int ThirdMax(int[] nums) {
        Array.Sort(nums);
        int count = 0;
        for(int i = nums.Length - 1; i >= 1; i--) {
            if(nums[i] != nums[i - 1]) count++;
            if(count == 2) {
                return nums[i - 1];
            }
        }
        return nums[nums.Length - 1];
    }

    private static int ThirdMax2(int[] nums) {
        var sorted = new SortedSet<int>();
        for(int i = 0; i < nums.Length; i++) {
            sorted.Add(nums[i]);
            if(sorted.Count > 3) {
                sorted.Remove(sorted.ElementAt(0));
            }
        }
        return sorted.Count == 3 ? sorted.ElementAt(0) : sorted.ElementAt(sorted.Count - 1);
    }

}

以上给出2种算法实现,以下是这个案例的输出结果:

1
1

分析:

ThirdMax的时间复杂度取决于 Array.Sort() 方法所使用的排序算法:

  • 若使用基于比较的先进排序算法,其时间复杂度为: O(nlogn) ,加上一个线性的分析过程,其时间复杂度仍为: O(nlogn) ;
  • 若不使用基于比较的算法,而是使用计数、基数、桶排序等空间换时间的线性排序算法,那么ThirdMax的时间复杂度为2倍的线性,结果仍然为线性,即为: O(n) 。

ThirdMax2的时间复杂度不能直接认定是 O(n) ,因为使用了不重复的有序集合,每次添加数据都会导致sorted被重新排序。但是因为sorted中最多只包含3个数字(到达4时被删除1个),所以即便使用了糟糕的 O(n^{2}) 的冒泡,其复杂度也仅为常数 9,即为常量时间内完成排序。在这种情况下ThirdMax2的时间复杂度应该为9倍的线性,其结果仍然为线性,即为: O(n) 。

具体的时间复杂度的分析应该具体对待,如果把冒泡的内循环封装成一个方法,便认为冒泡是 O(n) 那就贻笑大方了。

本文由 .Net中文网 原创发布,欢迎大家踊跃转载。

转载请注明本文地址:https://www.byteflying.com/archives/3710

发表评论

登录后才能评论