有一个整数数组,请你根据快速排序的思路,找出数组中第 k 大的数。
给定一个整数数组 a ,同时给定它的大小n和要找的 k ,请返回第 k 大的数(包括重复的元素,不用去重),保证答案存在。
要求:时间复杂度 ,空间复杂度
数据范围:, ,数组中每个元素满足
有一个整数数组,请你根据快速排序的思路,找出数组中第 k 大的数。
[1,3,5,2,2],5,3
2
[10,10,9,9,8,7,5,6,4,3,4,2],12,3
9
去重后的第3大是8,但本题要求包含重复的元素,不用去重,所以输出9
class Solution { public: int findKth(vector<int> a, int n, int K) { // write code here if (K > n) { return -1; } quick_sort(a, 0, n-1); return a[n-K]; } void quick_sort(vector<int>& a, int iLow, int iUpper) { if (iLow >= iUpper) { return; } int iIndex = iLow; int jIndex = iUpper; int iBaseValue = a.at(iIndex); while (iIndex < jIndex) { while(iIndex < jIndex && a.at(jIndex) >= iBaseValue) { jIndex--; } while (iIndex <jIndex && a.at(iIndex) <= iBaseValue) { iIndex++; } if (iIndex < jIndex) { std::swap(a[iIndex], a[jIndex]); } } a[iLow] = a[iIndex]; a[iIndex] = iBaseValue; quick_sort(a, iIndex+1, iUpper); quick_sort(a, iLow, iIndex-1); } };
class Solution { public: vector<int> partition(vector<int> &a,int left,int right) { int less=left-1; int more=right; while(left<more) { if(a[left]<a[right]) { swap(a[++less],a[left++]); } else if(a[left]>a[right]) { swap(a[--more],a[left]); } else { left++; } } swap(a[right],a[more]); return {less+1,more}; } void quicksort(vector<int> &a,int left,int right) { if(left>=right) return; int index=left+rand()%(right-left+1); swap(a[index],a[right]); vector<int> recv=partition(a,left,right); quicksort(a,left,recv[0]-1); quicksort(a,recv[1]+1,right); } int findKth(vector<int> a, int n, int K) { // write code here quicksort(a,0,n-1);//注意传入的是n-1不是n return a[n-K]; } };手写快排
# -*- coding:utf-8 -*- class Solution: def quick_sort(self,a,left,right,k): if left < right: mid = self.partition(a,left,right) if mid < k: self.quick_sort(a,left,mid-1,k) elif mid > k: self.quick_sort(a,mid+1,right,k) else: return a else: return a def partition(self,a,left,right): pivot = left while left != right: while left < right and a[right] > a[pivot]: right -= 1 while left < right and a[left] <= a[pivot]: left += 1 if left < right: a[left],a[right] = a[right],a[left] a[pivot],a[left] = a[left],a[pivot] return left def findKth(self, a, n, K): # write code here return self.quick_sort(a,0,n-1,n-K)[n-K]
# -*- coding:utf-8 -*- class Solution: def quick_sort(self,a,left,right,k): mid = self.partition(a,left,right) if mid == k: return a[mid] elif mid > k: return self.quick_sort(a,left,mid-1,k) elif mid < k: return self.quick_sort(a,mid+1,right,k) def partition(self,a,left,right): pivot = left while left != right: while left < right and a[right] > a[pivot]: right -= 1 while left < right and a[left] <= a[pivot]: left += 1 if left < right: a[left],a[right] = a[right],a[left] a[pivot],a[left] = a[left],a[pivot] return left def findKth(self, a, n, K): # write code here return self.quick_sort(a,0,n-1,n-K)
import java.util.*; public class Solution { public int findKth(int[] a, int n, int K) { // write code here if (a == null || n == 0 || K < 1 || K > n){ return -1; } return partition(a, 0, n - 1, n - K); } private int partition(int[] a, int start, int end, int K) { if (start >= end) { return a[K]; } int left = start, right = end; int pivot = a[(start + end) / 2]; while (left <= right) { while (left <= right && a[left] < pivot) { left++; } while (left <= right && a[right] > pivot) { right--; } if (left <= right) { swap(a, left, right); left++; right--; } } if (K <= right) { return partition(a, start, right, K); } if (K >= left) { return partition(a, left, end, K); } return a[K]; } private void swap(int[] a, int i, int j) { int tmp = a[i]; a[i] = a[j]; a[j] = tmp; } }
import java.util.*; public class Solution { /** 找出数组中第K大的数:表示要从大到小排,找到第k大的数字 */ public int findKth(int[] a, int n, int K) { int low = 0, high = n - 1; while(low <= high) { int i = low, j = high; //基准数 int temp = a[low]; while(i < j) { // 从右到左找到第一个 < temp 的数的下标 while(i < j && a[j] <= temp) { j--; } // 从左到右找到第一个 > temp 的数的下标 while(i < j && a[i] >= temp){ i++; } if(i < j) { // 交换下标为 i,j 的两个数 swap(a, i, j); } } //最后将基准为与i和j相等位置的数字交换 swap(a, low, i); if(i == K - 1){ return a[K-1]; }else if(i < K - 1) { // K-1 位于高分段 low = i + 1; }else { // K-1 位于低分段 high = i - 1; } } return -1; } /** 交换下标为i,j的两个元素 */ private void swap(int[] a, int i, int j) { int c = a[i]; a[i] = a[j]; a[j] = c; } }
import java.util.*; public class Solution { public int findKth(int[] a, int n, int K) { // write code here int[] arr = Arrays.copyOf(a, a.length); quicksort(a, 0, a.length - 1); return a[n-K]; } public void swap(int[] a, int i,int j){ int temp = a[i]; a[i]=a[j]; a[j]=temp; } public int partition(int[] a,int start,int end){ //设置基准值的索引 int pivot = start; //记录下一个放比基准值小的值的索引 int index = start+1; //遍历,找到比基准值小的,依次放在基准值后 //注意这里要取end的值,因为我这end是最后的索引值 //注意这里要取end的值,因为我这end是最后的索引值 //注意这里要取end的值,因为我这end是最后的索引值 //为什么说三遍,因为我一开始一直没注意 for(int i=index;i<=end;i++){ if(a[i]<a[pivot]){ swap(a,i,index); index ++; } } //由于此时index位置的值必然大于等于基准值,所以把基准值和index-1位置的值互换,这样一来就排好序了 swap(a,pivot,index-1); //返回的也是基准值的索引 return index-1; } public int[] quicksort(int[] arr, int start,int end){ if(start<end){ //返回基准值的索引,在左边的都是比它小的 int partition = partition(arr, start, end); //分别对两边进行排序 quicksort(arr,start,partition-1); quicksort(arr,partition+1,end); } return arr; } }
import java.util.*; public class Solution { /** Partition Algorithm */ public static int partition(int[] a, int left, int right) { int j = left; int t = right; while (j < t) { if (a[j + 1] > a[j]) { //swap a[j + 1] and a[j] int temp = a[j + 1]; a[j + 1] = a[j]; a[j] = temp; j = j + 1; } else { // swap a[j + 1] and a[t] int temp = a[j + 1]; a[j + 1] = a[t]; a[t] = temp; t = t - 1; } } return j; } /** QuickSort Algorithm*/ public static void QS(int[] a, int h, int k) { int h1 = h; int k1 = k; // invariant a[h..k] is sorted if a[h1..k1] is sorted while (k1 - h1 > 0) { // when a[h1..k1] has more than one element int j = partition(a, h1, k1); // a[h1..j-1] >= a[j] >= a[j+1..k1] if (j - h1 < k1 - j) { // if a[h1..j-1] smaller than a[j+1..k1] QS(a, h1, j - 1); h1 = j + 1; } else { QS(a, j + 1, k1); k1 = j - 1; } } } public int findKth(int[] a, int n, int K) { QS(a, 0, n - 1); return a[K - 1]; } }
1.设置初始查找区间 low=0;high=n-1; 2.以ai为轴值对序列a[low]-a[high]进行一次划分,得到轴值的位置s 3.以轴值位置s与k进行比较 3.1 如果k-1等于s,则将as作为结果返回 3.2 如果s<k-1 则low=s+1;转步骤2。 3.3如果s>k-1,则high=s-1;转步骤2。 找第K大的数使用降序比较方便,而找第K小数使用升序。class Solution { public: int findKth(vector<int>a, int n, int K) { // write code here int low=0,high=n-1; int s=partition(a,low,high); while(1){ if(s==K-1) return a[s]; else if(s<K-1) { low=s+1; s=partition(a,s+1,high); } else { high=s-1; s=partition(a,low,s-1) } } } int partition(vector<int>&a,int low,int high) { int privot=a[low]; while(low<high){ while(low<high&&a[high]<=privot)high--; a[low]=a[high]; while(low<high&&a[low]>=privot)low++; a[high]=a[low]; } a[low]=privot; return low; } };
int partit(vector<int> &a, int low, int high){ int piov = a[low]; while(high > low){ while(high > low && a[high] <= piov) --high; a[low] = a[high]; while(high > low && a[low] >= piov) ++low; a[high] = a[low]; } a[low] = piov; return low; } int findKth(vector<int> a, int n, int K) { // write code here int pos = 0; int high = n-1, low = 0; while(high >= low){ pos = partit(a, low, high); if(pos == K-1) break; else if(pos < K-1) low = pos+1; else high = pos-1; } return a[pos]; }
import java.util.*; public class Solution { public int findKth(int[] a, int n, int K) { // write code here quickSort(a,0,n-1); return a[n-K];//看清楚是第K大,不是第K小,我是从小到大排的数 } //下面是快排经典代码 public void quickSort(int[] a,int start,int end){ if(start<end){ int i=partition(a,start,end); quickSort(a,i+1,end); quickSort(a,start,i-1); } } public int partition(int[]a,int p,int q){//以数组第一个数为基准将数组分为左右两部分,左边小于基数,右边大于基数,然后把基数放在数组中合适的位置,返回该位置 int x=a[p]; int i=p; for(int j=p+1;j<=q;j++){ if(a[j]<x){ swap(a,i+1,j); i++; } } swap(a,p,i); return i; } public void swap(int[]a ,int i,int j){ int temp=a[i]; a[i]=a[j]; a[j]=temp; } }
# -*- coding:utf-8 -*- class Solution: def findKth(self, a, n, K): # write code here for i in range(K-1): a.pop(a.index(max(a))) return max(a)
import java.util.*; public class Solution { public int findKth(int[] a, int n, int K) { Arrays.sort(a); return a[n-K]; } }
//使用快排,按照从大到小排序 int quickSortKth(vector<int> a, int start,int end, int K) { //划分 int left,right; int pivot,temp; left = start; right = end-1; pivot = a[left]; while (left < right){ while (left < right && a[right] <= pivot){ right --; } temp = a[left]; a[left] = a[right]; a[right] = temp; while (left < right && a[left] >= pivot){ left ++; } temp = a[left]; a[left] = a[right]; a[right] = temp; } a[left] = pivot; //找到划分位置 if(K == left+1){ return a[left]; }else if(K < left+1){ return quickSortKth(a,start,left,K); }else if(K > left+1){ return quickSortKth(a,left+1,end,K); } return -1; } int findKth(vector<int> a, int n, int K) { return quickSortKth(a,0,n,K); }
importjava.util.*;public clas sSolution {public int findKth(int[] a, intn, intK) {quickSort(a,0, n-1);return a[n-K];}public static void quickSort(int source[], int low, int high){inti,j,x;if(low<high){i= low;j= high;x= source[i];while(i<j){while(i<j &&source[j]>x){j--;}if(i<j){source[i]=source[j];i++;}while(i< j&&source[i]<x){i++;}if(i<j){source[j]=source[i];j--;}}source[i]=x;quickSort(source,low,i-1);quickSort(source,i+1,high);}}}
class Solution { public: int partition(vector<int> &nums, int begin, int end) { int pivot = nums[begin]; int pivot_index = begin; for(int i=begin+1; i!=end;i++){ if(nums[i] >= pivot){ pivot_index+=1; if(pivot_index != i){ swap(nums[i], nums[pivot_index]); } } } swap(nums[begin], nums[pivot_index]); return pivot_index; } int findKth(vector<int> &nums, int n, int k) { return find_k(nums, 0, nums.size(), k); } int find_k(vector<int> &nums, int begin, int end, int k){ if( k<=0 || begin>end-1){ return -1; } int position = partition(nums, begin, end); int left_length = position-begin; if(left_length== k-1){ return nums[position]; } else if(left_length > k-1){ return find_k(nums, begin, position, k); } else{ return find_k(nums, position+1, end, k-left_length-1); } } };