[LeetCode] 215. Kth Largest Element in an Array 數組中第k大的元素


Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

Example 1:

Input: [3,2,1,5,6,4] and k = 2
Output: 5

Example 2:

Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4

Note: 
You may assume k is always valid, 1 ≤ k ≤ array's length.

找出一個非排序數組中第k大的元素。

解法1:排序法。使用常規排序方法后找到數組中對應下標的值。

解法2:將數組內容存入一升序優先隊列中,進行k-1次pop操作,那么隊尾的元素就是第k大的數字。

解法3:最大堆MaxHeap。使用數組內容構建一個最大堆,通過每次pop出堆頂后繼續維護堆的結構,直到滿足一定的次數(最大堆k-1次,最小堆size-k次),堆頂的元素就是第k大的數字,實現的效果與優先隊列相同。

解法4:Quick Select, 利用快排的partition函數思想,選定一個數組內的值作為pivot,將小於pivot的數字放到pivot右邊,大於等於pivot的數字放到pivot左邊。接着判斷兩邊數字的數量,如果左邊的數量小於k個,說明第k大的數字存在於pivot及pivot右邊的區域之內,對右半區執行partition函數;如果右邊的數量小於k個,說明第k大的數字在pivot和pivot左邊的區域之內,對左半區執行partition函數。直到左半區剛好有k-1個數,那么第k大的數就已經找到了。

Java: Sort, T: O(nlogn) S: O(1)

public class Solution {
    public int findKthLargest(int[] nums, int k) {
        Arrays.sort(nums);
        return nums[nums.length - k];
    }
}

Java: MaxHeap, T: O(nlogk) S: O(k)

public class Solution {
    public int findKthLargest(int[] nums, int k) {
        PriorityQueue<Integer> p = new PriorityQueue<Integer>();
        for(int i = 0 ; i < nums.length; i++){
            p.add(nums[i]);
            if(p.size()>k) p.poll();
        }
        return p.poll();
    }
}

Java: Quick select, T: Avg O(n) Worst O(n^2), S: O(1)

public class Solution {
    public int findKthLargest(int[] nums, int k) {
        return quickSelect(nums, k - 1, 0, nums.length - 1);
    }
    
    private int quickSelect(int[] arr, int k, int left, int right){
        int pivot = arr[(left + right) / 2];
        int orgL = left, orgR = right;
        while(left <= right){
            // 從右向左找到第一個小於樞紐值的數
            while(arr[left] > pivot){
                left ++;
            }
            // 從左向右找到第一個大於樞紐值的數
            while(arr[right] < pivot){
                right --;
            }
            // 將兩個數互換
            if(left <= right){
                swap(arr, left, right);
                left ++;
                right --;
            }
        }
        // 最后退出的情況應該是右指針在左指針左邊一格
        // 這時如果右指針還大於等於k,說明kth在左半邊
        if(orgL < right && k <= right) return quickSelect(arr, k, orgL, right);
        // 這時如果左指針還小於等於k,說明kth在右半邊
        if(left < orgR && k >= left) return quickSelect(arr, k, left, orgR);
        return arr[k];
    
    }
    
    private void swap(int[] arr, int idx1, int idx2){
        int tmp = arr[idx1] + arr[idx2];
        arr[idx1] = tmp - arr[idx1];
        arr[idx2] = tmp - arr[idx2];
    
    }
} 

Python: Sort

class Solution:
    # @param {integer[]} nums
    # @param {integer} k
    # @return {integer}
    def findKthLargest(self, nums, k):
        return sorted(nums, reverse=True)[k - 1]

Python: Max Heap

from heapq import *
class Solution(object):
    def findKthLargest(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        if not nums:
            return -1
        
        h = []
        for i in xrange(len(nums)):
            if len(h) < k:
                heappush(h, nums[i])
            else:
                if h[0] < nums[i]:
                    heappop(h)
                    heappush(h, nums[i])

        return h[0]

Python: Quick select

import random
class Solution:
    def findKthLargest(self, nums, k):
        pivot = random.choice(nums)
        nums1, nums2 = [], []
        for num in nums:
            if num > pivot:
                nums1.append(num)
            elif num < pivot:
                nums2.append(num)
        if k <= len(nums1):
            return self.findKthLargest(nums1, k)
        if k > len(nums) - len(nums2):
            return self.findKthLargest(nums2, k - (len(nums) - len(nums2)))
        return pivot

Python: Quick select

class Solution:
    # @param {integer[]} nums
    # @param {integer} k
    # @return {integer}
    def findKthLargest(self, nums, k):
        left, right = 0, len(nums) - 1
        while left <= right:
            pivot_idx = randint(left, right)
            new_pivot_idx = self.PartitionAroundPivot(left, right, pivot_idx, nums)
            if new_pivot_idx == k - 1:
                return nums[new_pivot_idx]
            elif new_pivot_idx > k - 1:
                right = new_pivot_idx - 1
            else:  # new_pivot_idx < k - 1.
                left = new_pivot_idx + 1
        
    def PartitionAroundPivot(self, left, right, pivot_idx, nums):
        pivot_value = nums[pivot_idx]
        new_pivot_idx = left
        nums[pivot_idx], nums[right] = nums[right], nums[pivot_idx]
        for i in xrange(left, right):
            if nums[i] > pivot_value:
                nums[i], nums[new_pivot_idx] = nums[new_pivot_idx], nums[i]
                new_pivot_idx += 1
            
        nums[right], nums[new_pivot_idx] = nums[new_pivot_idx], nums[right]
        return new_pivot_idx

C++: Sort

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end());
        return nums[nums.size() - k];
    }
};

C++: Priority queque

class Solution {
    public:
        int findKthLargest(vector<int>& nums, int k) {
            /** priority_queue<int, vector<int>, less<int>> q; **/
            priority_queue<int, vector<int>> q;
            int len=nums.size();
            for(int val:nums){
                q.push(val);
            }
            while(q.size() > len-k+1){
                q.pop();
            }
            return q.top();
        }
    };

 

C++: MaxHeap

class Solution {
    public:
        int findKthLargest(vector<int>& nums, int k) {
            //max heap method
            //min heap method
            //order statistics
            make_heap(nums.begin(), nums.end());
            int result;
            for(int i=0; i<k; i++){
                result=nums.front();
                pop_heap(nums.begin(), nums.end());
                nums.pop_back();
            }
            return result;
        }
    };

C++: Quick sort, partition

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int high = nums.size();
        int low = 0;
        while (low < high) {
            int i = low;
            int j = high-1;
            int pivot = nums[low];
            while (i <= j) {
                while (i <= j && nums[i] >= pivot)
                    i++;
                while (i <= j && nums[j] < pivot)
                    j--;
                if (i < j)
                    swap(nums[i++],nums[j--]);
            }
            swap(nums[low],nums[j]);

            if (j == k-1)
                return nums[j];
            else if (j < k-1)
                low = j+1;
            else
                high = j;
        }
    }
};

  

All LeetCode Questions List 題目匯總

  

  

 


免責聲明!

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



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