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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM