题目:以尽量高的效率求出一个乱序数组中按数值顺序的第k个元素值。(升序)
这里可以利用快排找主元的部分:我们可以发现,快排找主元部分会把主元位置调整到使得左边比主元小,右边比主元大,最后返回主元的下标。而返回的主元下标就可以说明他在数组中有多少个元素比他小
public class 第K小的数 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = {3,9,7,6,1,2};
int num = SelectK(arr,0,arr.length-1,1);
System.out.println(num);
}
/*
期望时间复杂度:O(n)
最差O(n^2)
*/
public static int SelectK(int[] arr,int start,int end,int k) {
int q = 快排优化.patitiion(arr, start, end);
int temp =q+1;//这里用temp是因为下面q会被用来作为返回的数组元素的下标,如果用q加1的话会导致每次返回的元素并不是想要的
if(temp==k) {
return arr[q];
}
else if(temp>k) {
return SelectK(arr,start,q-1,k);
}
else return SelectK(arr,q+1,end,k);
}
}
import lanqiao.Swap;
public class 快排优化 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//2.绝对中值法
//3.待排序列较短时用插入排序,插入排序是n*(n-1)/2,快排是nlgn+n,所以序列小于等于8时用插入
}
//法一:三点中值法
public static int patitiion(int[] arr,int start,int end) {
//优化,在start,end,mid中找主元
int midindexof = start+((end-start)>>1);
int midindexvalueof = -1;
int zhuyuan;
if(arr[start]>arr[end]&&arr[end]>arr[midindexof]) {
zhuyuan = arr[end];
Swap.swap(arr, start, end);
}else if(arr[end]>arr[start]&&arr[start]>arr[midindexof]) {
zhuyuan = arr[start];
}else {
zhuyuan = arr[midindexof];
Swap.swap(arr, start, midindexof);
}
//左指针
int left = start+1;
int right = end;//右指针
while(left<=right) {
//左侧大于主元就停下,特殊情况会越界
while(left<=right&&arr[left]<=zhuyuan) {
left++;
}
//右侧小于等于主元就停下
while(left<=right&&arr[right]>zhuyuan) {
right--;
}
if(left<right)
Swap.swap(arr, left, right);//停下后元素交换
}
Swap.swap(arr, start, right);
return right;
}
}