1. 程式人生 > 其它 >215. 陣列中的第K個最大元素_中等_陣列

215. 陣列中的第K個最大元素_中等_陣列

暴力,排序取值

class Solution {

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

}

優先佇列

    //思路是建立一個大小為k的優先佇列,對每一個元素判斷和優先佇列對頭的元素(最小值,小頂堆)
    //進行比較,如果對頭元素小,則移除加入新的元素,所以最終佇列就是前k大,隊頭就是我們要的
    public int findKthLargest(int[] nums, int k) {
        PriorityQueue  queue 
= new PriorityQueue(k); for (int i = 0; i < nums.length; i++) { // System.out.println(queue.size()); if(queue.size()<k){ queue.add(nums[i]); }else{ if(nums[i]> (int)queue.peek()){ // System.out.println(queue.peek());
queue.poll(); queue.add(nums[i]); } } } return (int)queue.peek(); }

快排(每次確定一個指定大的資料,當為k時就可以返回)

class Solution {
    //用一個全域性變數來記錄quickSelect的結果
    private int num;

    public int findKthLargest(int[] nums, int
k) { // quickSelect(nums,k,0,nums.length - 1);//快排選擇 int num = heapSelect(nums, k);//堆選擇 return num; } /** * 快排選擇 * @param nums 陣列 * @param k 第幾大 * @param left 左邊界 * @param right 右邊界 */ public void quickSelect(int[] nums,int k,int left,int right){ //遞迴終止條件 if(left > right){ return; } int pivot = nums[left];//基準值 int leftIndex = left;//左指標 int rightIndex = right;//右指標 //用挖坑法逐步替換元素,使基準值歸位 while(leftIndex < rightIndex){ //在右邊尋找一個小於基準值的數,並與左指標所在位置交換 while(leftIndex < rightIndex && nums[rightIndex] >= pivot){ rightIndex--; } if(leftIndex < rightIndex){ nums[leftIndex] = nums[rightIndex]; } //在左邊尋找一個大於基準值的數,並與右指標所在位置交換 while(leftIndex < rightIndex && nums[leftIndex] < pivot){ leftIndex++; } if(leftIndex < rightIndex){ nums[rightIndex] = nums[leftIndex]; } } nums[leftIndex] = pivot;//將基準值歸位 //以上都是快排的基本操作,接下來則是利用快排找出第k大的數 //leftIndex是基準值的位置,以它為分界線,看第k大的位置在左邊還是右邊,進而對相應區域使用快排 //如果第k大的數已經歸位,則返回 if(leftIndex == nums.length - k){ num = nums[leftIndex]; return; }else if(leftIndex > nums.length - k){ quickSelect(nums,k,left,leftIndex - 1); }else if(leftIndex < nums.length - k){ quickSelect(nums,k,leftIndex + 1,right); } } //交換陣列中兩個數的位置 public void swap(int[] nums,int index1,int index2){ int temp = nums[index1]; nums[index1] = nums[index2]; nums[index2] = temp; } /** * 調整堆 * @param nums 陣列 * @param index 所要調整的元素下標 * @param endIndex 此次調整的範圍 */ public void adjustHeap(int[] nums,int index,int endIndex){ //利用挖坑法調整,先儲存nums[index],待找到其應在的位置時,再填充上去 int temp = nums[index]; //2 * index + 1是左子結點的下標,所謂調整,就是不斷比較父結點與子結點的大小,從而將父結點調整到合適的位置 for(int i = 2 * index + 1;i <= endIndex;i = 2 * i + 1){ //先比較左右子結點哪個大,大的那個需要和父節點交換 if(i + 1 <= endIndex && nums[i + 1] > nums[i]){ i = i + 1; } //如果大的那個子結點比父結點大,則交換 if(nums[index] < nums[i]){ swap(nums,index,i); index = i;//交換以後要記得調整下標 }else{//如果父結點比兩個子結點都大,則調整結束 break; } } nums[index] = temp;//將坑填上,也就是將父結點放到其應在的位置 } //堆選擇 public int heapSelect(int[] nums,int k){ int num = 0;//用來記錄結果 //首先建堆,建堆就是從最後一個非葉子結點開始,不斷調整,直到根結點 //最後一個非葉子結點的下標是(nums.length - 2)/2,這個是可以證明的,可以上網查一下 for(int i = (nums.length - 2)/2;i >= 0;i--){ adjustHeap(nums,i,nums.length - 1); } //所謂堆排序,就是不斷將堆頂元素交換到堆尾 //由於交換後破壞了堆,所以每次交換後都需要調整,以滿足堆的要求 //通過把堆頂元素交換到堆尾,並縮小堆尾範圍,逐步使陣列達到有序的狀態 for(int endIndex = nums.length - 1;endIndex >= 0;endIndex--){ adjustHeap(nums,0,endIndex);//調整堆 swap(nums,0,endIndex);//交換堆頂和堆尾 //如果第k大元素已經歸位,則返回 if(endIndex == nums.length - k){ num = nums[endIndex]; } } return num; } }
作者:你的雷哥 出處:https://www.cnblogs.com/henuliulei/ 本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須在文章頁面給出原文連線,否則保留追究法律責任的權利。