LeetCode 215——陣列中的第 K 個最大元素
阿新 • • 發佈:2018-11-10
1. 題目
在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。
示例 1:
輸入: [3,2,1,5,6,4] 和 k = 2
輸出: 5
示例 2:
輸入: [3,2,3,1,2,4,5,5,6] 和 k = 4
輸出: 4
說明:
你可以假設 k 總是有效的,且 1 ≤ k ≤ 陣列的長度。
2. 思路
-
針對這個題目,我們首先想到的就是先用排序演算法對資料從大到小進行排序,然後直接返回降序後的第 K 個元素即可。
-
另外,我們也可以借鑑快速排序的思想。每次選取一個 pivot,將大於 pivot 的數放在 pivot 左邊,將小於 pivot 的數放在 pivot 右邊。
-
這時候,如果 pivot 正好是第 K 個數據,則 pivot 就是陣列中的第 K 個最大元素。
-
如果 pivot 所在的位置小於 K ,則說明陣列中的第 K 個最大元素位於 pivot 的右邊。此時,假設 pivot 的位置為 which_max,which_max 是幾就代表 pivot 是陣列中的第幾個最大元素。這時候,我們再從 pivot 右邊的資料中找到第 (K-which_max) 個最大元素即可。
-
如果 pivot 所在的位置大於 K ,則說明陣列中的第 K 個最大元素位於 pivot 的左邊。這時候,pivot 左邊的資料全部大於 pivot,我們繼續從 pivot 左邊的資料中找第 K 個最大元素
-
而其中的快速排序演算法實現可以有兩種思想,具體可參考此處。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
return quick_sort(nums, 0, nums.size()-1, k);
}
// 第一種快排思想
int quick_sort(vector<int>& data, int left, int right, int k)
{
int i = left;
int j = right;
int pivot = data[right];
int len = right - left + 1;
if (left < right)
{
// 從大到小對陣列進行快排
while(i < j)
{
while(i < j && data[i] >= pivot) // 從左往右找第一個比 pivot 小的數
{
i++;
}
if (i < j)
{
data[j--] = data[i];
}
while(i < j && data[j] <= pivot) // 從右往左找第一個比 pivot 大的數
{
j--;
}
if (i < j)
{
data[i++] = data[j];
}
}
data[i] = pivot; // 此時 i == j
// pivot 此時位於索引 i 處,i - left + 1 表示 pivot 是第幾大的數
int which_max = i - left + 1;
if (which_max == k) // pivot 正好是第 k 大的數
{
return pivot;
}
// 第 k 大的數在 pivot 右邊,問題轉化為找右邊陣列第 (k - which_max) 大的元素
// 比如 pivot 是第四大的數,要找第五大的數,則繼續找右邊陣列第一大的數即可
else if(which_max < k)
{
return quick_sort(data, i + 1, right, k - which_max);
}
// 第 k 大的數在 pivot 左邊,問題轉化為找左邊陣列第 k 大的元素
// 比如 pivot 是第三大的數,要找第二大的數,則繼續找左邊陣列第二大的數即可
else
{
return quick_sort(data, left, i - 1, k);
}
}
else
{
return pivot;
}
}
// 第二種快排思想
int quick_sort(vector<int>& data, int left, int right, int k)
{
int i = left;
int j = left;
int pivot = data[right];
int len = right - left + 1;
if (left < right)
{
// 從大到小對陣列進行快排
for (; j < right; j++)
{
if (data[j] > pivot)
{
int temp = data[i];
data[i] = data[j];
data[j] = temp;
i++;
}
}
data[j] = data[i];
data[i] = pivot;
// pivot 此時位於索引 i 處,i - left + 1 表示 pivot 是第幾大的數
int which_max = i - left + 1;
if (which_max == k) // pivot 正好是第 k 大的數
{
return pivot;
}
// 第 k 大的數在 pivot 右邊,問題轉化為找右邊陣列第 (k - which_max) 大的元素
// 比如 pivot 是第四大的數,要找第五大的數,則繼續找右邊陣列第一大的數即可
else if(which_max < k)
{
return quick_sort(data, i + 1, right, k - which_max);
}
// 第 k 大的數在 pivot 左邊,問題轉化為找左邊陣列第 k 大的元素
// 比如 pivot 是第三大的數,要找第二大的數,則繼續找左邊陣列第二大的數即可
else
{
return quick_sort(data, left, i - 1, k);
}
}
else
{
return pivot;
}
}
};
獲取更多精彩,請關注「seniusen」!