1. 程式人生 > >LeetCode 215——陣列中的第 K 個最大元素

LeetCode 215——陣列中的第 K 個最大元素

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 個最大元素。
    1

  • 如果 pivot 所在的位置小於 K ,則說明陣列中的第 K 個最大元素位於 pivot 的右邊。此時,假設 pivot 的位置為 which_max,which_max 是幾就代表 pivot 是陣列中的第幾個最大元素。這時候,我們再從 pivot 右邊的資料中找到第 (K-which_max) 個最大元素即可。
    2

  • 如果 pivot 所在的位置大於 K ,則說明陣列中的第 K 個最大元素位於 pivot 的左邊。這時候,pivot 左邊的資料全部大於 pivot,我們繼續從 pivot 左邊的資料中找第 K 個最大元素

    即可。
    3

  • 而其中的快速排序演算法實現可以有兩種思想,具體可參考此處

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」!
seniusen