每天一道LeetCode-----找到給定陣列中第三大的值
阿新 • • 發佈:2019-01-06
要求找到給定陣列中第三大的數。其中第一大的數,第二大的數,第三大的數互不相同,即嚴格的小於關係。並且規定時間複雜度是O(n)。另外如果找不到第三大的數,則返回陣列中第一大的數
可以用三個變數first, second, third分別記錄第一大第二大以及第三大的數,初始化時是整數範圍的最小值,在隨後遍歷陣列的過程中進行比較(假設遍歷到的數用n表示)
- 如果n大於first, 則將second賦值給third, first賦值給second,n賦值給first
- 如果n大於second小於first,則將second賦值給thid,n賦值給second
- 如果n大於third,則將n賦值給third
這樣實現有一些侷限性,如果輸入的陣列中包含整數的最小值(即first,second,third的初始值INT32_MIN),那麼就無法區分到底是找到了第三大的數(它的值是INT32_MIN)還是沒有找到(因為third的值沒有改變)
解決方法時將初始值設定的再小一點,即INT64_MIN,但是如果輸入的陣列包含的資料偏偏就是64位的就沒有辦法了
程式碼實現如下
class Solution {
public:
int thirdMax(vector<int>& nums) {
// 因為int的範圍小於long long int的範圍,所以這種方式可解
// 但是如果輸入的是vector<long long int> 就沒有辦法了
long long int first = INT64_MIN, second = INT64_MIN, third = INT64_MIN;
for(auto& n : nums) {
// 如果小於third或者和第一/二大的數相等,則不進行賦值
if(n <= third || n == second || n == first) {
continue;
}
third = n;
// 進行大小比較後交換資料
if(third > second) swap(second, third);
if(second > first) swap(first, second);
}
return third == INT64_MIN ? first : third;
}
};
鑑於上述的侷限性,需要換一種思路解決,但是對於時間複雜度的要求就無法滿足了。
考慮到題目中要求的時間複雜度是O(n),而二叉搜尋樹插入刪除的時間複雜度是O(lgn),所以可以考慮用set實現,同時也可以受益於set的去重能力,總的時間複雜度是O(nlogn)
程式碼實現如下
class Solution {
public:
int thirdMax(vector<int>& nums) {
set<int> s;
for(auto& n : nums) {
s.emplace(n);
if(s.size() > 3) {
s.erase(s.begin());
}
}
return s.size() == 3 ? *s.begin() : *s.rbegin();
}
};