[Leetcode] Kth Largest Element in an Array 數組中第K大元素

Kth Largest Element in an Array

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.數組

For example, Given [3,2,1,5,6,4] and k = 2, return 5.函數

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

優先隊列

複雜度

時間 O(NlogK) 空間 O(K)指針

思路

遍歷數組時將數字加入優先隊列(堆),一旦堆的大小大於k就將堆頂元素去除,確保堆的大小爲k。遍歷完後堆頂就是返回值。code

代碼

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();
    }
}

排序法

複雜度

時間 O(NlogN) 空間 O(1)排序

思路

將數組排序後,返回第k個元素。隊列

代碼

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

快速選擇 Quick Select

複雜度

時間 Avg O(N) Worst O(N^2) 空間 O(1)element

思路

跟快速排序一個思路。先取一個樞紐值,將數組中小於樞紐值的放在左邊,大於樞紐值的放在右邊,具體方法是用左右兩個指針,若是他們小於樞紐值則將他們換到對面,一輪事後記得將樞紐值賦回分界點。若是這個分界點是k,說明分界點的數就是第k個數。不然,若是分界點大於k,則在左半邊作一樣的搜索。若是分界點小於k,則在右半邊作一樣的搜索。it

注意

  • helper函數的kk-1,由於咱們下標從0開始的,咱們要比較k和下標,來肯定是否左半部分有k個數字。io

  • 互換左右時,也要先判斷left <= right

代碼

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];
    
    }
}
相關文章
相關標籤/搜索