1. 程式人生 > >leetcode-414-Third Maximum Number

leetcode-414-Third Maximum Number

long 重復元素 HERE maximum 文件 如何 ssi 以及 tin

題目描述:

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).

Example 1:

Input: [3, 2, 1]

Output: 1

Explanation: The third maximum is 1.

Example 2:

Input: [1, 2]

Output: 2

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

Example 3:

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.

要完成的函數:

int thirdMax(vector<int>& nums)

說明:

1、這道題目題意清晰,返回給定vector中的第三大的數值,如果沒有第三大的數,那麽返回最大的數。重復的數算一個,比如[2,2,3,1],2算是第二大的數,1是第三大的數。要求O(n)的時間復雜度

2、解法一:

沒有要求空間復雜度,只是要求時間復雜度為O(n),那麽我們可以定義三個整數,用來存放最大的整數,第二大的整數,第三大的整數。

然後對vector做一次遍歷,如果比max1大,那麽更新max1、max2、max3;如果比max1小但比max2大,那麽更新max2、max3;如果只比max3大,那麽更新max3;如果都不比這三個數大,那麽處理下一個數。

那麽max1、max2、max3的初始值應該是多少呢?

我們可以把它們設置為INT_MAX,這樣子無論最開始是什麽數,這三個數都會更新。

代碼如下:

    int thirdMax(vector<int>& nums) 
    {
        
int max1=INT_MIN,max2=INT_MIN,max3=INT_MIN; for(int i=0;i<nums.size();i++) {if(nums[i]==max1||nums[i]==max2||nums[i]==max3)//如果出現重復的數 { continue; } if(nums[i]>max1) { max3=max2; max2=max1; max1=nums[i]; } else if(nums[i]>max2) { max3=max2; max2=nums[i]; } else if(nums[i]>max3) { max3=nums[i]; } } }

上述代碼還沒有處理邊界情況,也就是當vector中沒有三個及三個以上不重復元素的時候,我們應該輸出max1。

那麽如何判斷vector中有沒有出現?當沒有出現的時候,我們發現max3為INT_MIN。似乎可以用這個作為判斷條件。

但是如果vector中有三個元素,其中一個為INT_MIN呢?我們不能用max3==INT_MIN來說明,max3沒被修改過,即vector中沒有三個及三個以上不重復元素。

那我們再細致地考慮下,修改代碼如下:

    int thirdMax(vector<int>& nums) 
    {
        int max1=INT_MIN,max2=INT_MIN,max3=INT_MIN,count=0;
        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]==INT_MIN)//判斷vector中有沒有出現INT_MIN
                count++;
            if(nums[i]==max1||nums[i]==max2||nums[i]==max3)
                continue;
            if(nums[i]>max1)
            {
                max3=max2;
                max2=max1;
                max1=nums[i];
            }
            else if(nums[i]>max2)
            {
                max3=max2;
                max2=nums[i];
            }
            else if(nums[i]>max3)
            {
                max3=nums[i];
            }
        }
        if(max3==INT_MIN)
        {
            if(count==0)//如果沒有出現INT_MIN在vector中,那麽好辦,如果max3==INT_MIN,說明根本就沒有三個不重復元素
                return max1;
            else
            {
                if(max2!=INT_MIN)//如果出現了,而且max3==INT_MIN,而max2不是,那麽說明有三個不重復元素
                    return max3;
                else //如果出現了,而且max3==INT_MIN,max2==INT_MIN,那麽說明有兩個或一個不重復元素
                    return max1;
            }
        }
        return max3;
    }

這種做法略微繁瑣,實測8ms,beats 84.33% of cpp submissions。

3、解法二:

上述2中解法可能有些朋友會覺得麻煩,沒有必要,我們把max1等這三個數改成LONG LONG的不就好了嗎?那麽就可以用max3是不是等於LLONG_MIN來判斷是否max3有修改過,即是否有多於三個元素在vector中。

下面附上這種方法的代碼:

    int thirdMax(vector<int>& nums) 
    {
        
        long long max1=LLONG_MIN,max2=LLONG_MIN,max3=LLONG_MIN;
        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]==max1||nums[i]==max2||nums[i]==max3)
            {
                continue;
            }
            if(nums[i]>max1)
            {
                max3=max2;
                max2=max1;
                max1=nums[i];
            }
            else if(nums[i]>max2)
            {
                max3=max2;
                max2=nums[i];
            }
            else if(nums[i]>max3)
            {
                max3=nums[i];
            }
        }
        if(max3==LLONG_MIN)
        {
            return max1;
        }
        return max3;
    }

這種做法比起解法一,減少了瑣碎的條件判斷,實測7ms,beats 98.73% of cpp submissions。

4、解法三:排序

排序也可以解決這個問題,但是排序沒有時間復雜度為O(n)。不過我們可以考慮部分快排。

代碼如下:

    int thirdMax(vector<int>& nums) 
    {
        set<int>s1(nums.begin(),nums.end());
        vector<int>v1(s1.begin(),s1.end());
        if(v1.size()==2)
            return max(v1[0],v1[1]);
        else if(v1.size()==1)
            return v1[0];
        nth_element(v1.begin(),v1.end()-3,v1.end());
        return v1[v1.size()-3];
    }

最開始用set去掉重復元素。

nth_element是頭文件algorithm中的函數,對vector進行升序快速排列,直到第二個參數,也就是上述代碼中v1.end()-3停留在最終位置。這是部分快排。

這種做法多了set和vector的定義以及初始化,部分快排時間復雜度為O(n),因為只對vector做了一遍遍歷。

實測12ms,beats 23.16% of cpp submissions。

leetcode-414-Third Maximum Number