leetcode_陣列中第k大的元素
阿新 • • 發佈:2018-11-10
215. 陣列中的第K個最大元素
在未排序的陣列中找到第 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 ≤ 陣列的長度。
方法一:先進行一次快速排序,在排好序的陣列中獲得第k-1個元素, 時間複雜度為O(nlogn).
class Solution { public int findKthLargest(int[] nums, int k) { quickSort(nums, 0, nums.length-1); return nums[k-1]; } //快排 public void quickSort(int[] a, int start, int end){ //遞迴入口 if (start>=end){ return; } int i=start; int j=end; int key=a[start]; //進行一次快排 while(i<j){ while(a[j]<=key && i<j){ j--; } while(a[i]>=key && i<j){ i++; } if(i<j){ int temp=a[j]; a[j]=a[i]; a[i]=temp; } } int temp = a[i]; a[i]=key; a[start]=temp; quickSort(a, start, i-1); quickSort(a, i+1, end); } }
方法二:經典思路,利用快排的思想實現,通過positition的位置進行判斷,降低時間複雜度,為O(n).
class Solution { public int findKthLargest(int[] nums, int k) { return findKth(nums, 0, nums.length-1, k-1); } private int positition(int[] arr, int l, int r){ //隨機選取標定點 int index = (int)(Math.random()*(r-l+1)+l); int temp = arr[index]; arr[index] = arr[l]; arr[l] = temp; int v = arr[l]; //雙路快排 int i=l+1, j=r; while (true){ //while判斷為真, 可以保證即使只有兩個元素時,即i=l+1=j 時,也可以進入迴圈 while (i<=r && arr[i]>v){ //i停下的位置一定是小於或等於v的位置 i++; } while (j>=l+1 && arr[j]<v){ //j停下的位置一定是大於或等於v的位置 j--; } if(i>j){ //只能取大於 break; } int temp = arr[i]; arr[i]=arr[j]; arr[j] = temp; i++; j--; } int temp1 = arr[l]; arr[l] = arr[j]; arr[j]= temp1; //j落在最後一個大於等於v的位置, i落在第一個小於等於v的位置,最終i不等於j, 而l處需要一個大於v的值,所以只能和 j 處的交換 return j; } private int findKth(int[] arr, int l, int r, int k){ if(l==r){ return arr[l]; } int p = positition(arr, l, r); if(k==p){ return arr[p]; }else if(k<p){ return findKth(arr, l, p-1, k); }else{ return findKth(arr, p+1, r, k); } } }