题目:以尽量高的效率求出一个乱序数组中按数值顺序的第k 的元素值

思路:这里很容易想到直接排序然后顺序查找,可以使用效率较高的快排,但是它的时间复杂度是O(nlgn),我们这里可以用一种简便的方法,不一定需要排序,使用快速排序中双向分区的扫描方法,这里使用的是优化过后的三点中值法,具体思想一样,只是主元的取法不一样。然后扫描出主元下标,然后根据主元的值将数组划分成一半大,一半小。然后再根据主元下标与k进行比较,如果相等,说明主元就是我们要找的数,如果大于k,说明k所代表的值在小的那边,继续向小的那部分递归,如果小于k,说明k代表的值在大的那边,继续向大的那部分递归。这样即可得出正确答案。这种方法的时间复杂度为O(n),因为每次递归都相当于舍弃掉了差不多一半的数。

代码:

import java.util.Arrays;

public class SelectK {

    public static void main(String[] args) {

        int arr[] = new int[10];
for(int i=0;i<10;i++){
arr[i] = (int) ((Math.random()+1)*10);
} System.out.println("查找前数组:"+Arrays.toString(arr));
int k = selectK(arr, 0, arr.length-1, 5);
System.out.println("查找出第k小的元素:"+k); } /**
*
* @param arr
* @param p 开始下标
* @param r 结束下标
* @param k 求第k小元素 (递增第k个元素)
* @return
*/
public static int selectK(int[] arr,int p,int r,int k){
int q = partition(arr, p, r); // 主元的下标
int qk = q - p + 1; // 主元是第几个元素
if (qk==k) {
return arr[q];
}else if (qk>k) {
return selectK(arr, p, q-1, k);
}else {
return selectK(arr, q+1, r, k-qk);
} }
//三点中值法
public static int partition(int[] arr, int p, int r) {
//优化,在p, r, mid之间,选一个中间值作为主元
int midIndex = p + ((r - p) >> 1);//中间下标
int midValueIndex = -1;//中值的下标
if(arr[p] <= arr[midIndex] && arr[p] >= arr[r]) {
midValueIndex = p;
}else if(arr[r] <= arr[midIndex] && arr[r] >= arr[p]) {
midValueIndex = r;
}else {
midValueIndex = midIndex;
}
swap(arr, p, midValueIndex);
int pivot = arr[p];
int left = p + 1; //左侧指针
int right = r; //右侧指针
while(left <= right) {
while(left <= right && arr[left] <= pivot) {
left++;
}
while(left <= right && arr[right] > pivot) {
right--;
}
if(left < right) {
swap(arr, left, right);
}
}
swap(arr, p, right);
return right;
} private static void swap(int[] A, int p, int bigger) {
int temp = A[p];
A[p] = A[bigger];
A[bigger] = temp; }
}

结果:

  

最新文章

  1. 浅谈Android系统移植、Linux设备驱动
  2. sublime text3使用小结
  3. 面向OPENCL的ALTERA SDK
  4. linux下samba的安装与使用
  5. linux笔记:文件系统管理-fdisk分区
  6. BZOJ-2186 沙拉公主的困惑 线性筛(筛筛筛)+线性推逆元
  7. CSS效果
  8. VI一个终端编辑多个文件的命令
  9. 【mac osx安装opencv,python总结】
  10. initWithNibName与viewDidLoad的执行关系以及顺序
  11. linux cp操作,每天学习一点
  12. Myeclipse默认编码设置
  13. CCScene,CCLayer,CCSprite,CCDirector
  14. BZOJ1131 POI2008 Sta 【树形DP】
  15. poj 2914(stoer_wanger算法求全局最小割)
  16. [ Openstack ] Openstack-Mitaka 高可用之 Rabbitmq-server 集群部署
  17. Python基础学习之序列(2)
  18. C. Glass Carving (CF Round #296 (Div. 2) STL--set的运用 &amp;amp;&amp;amp; 并查集方法)
  19. 【二叉树】hdu 1710 Binary Tree Traversals
  20. 前端--2、CSS基础

热门文章

  1. UiAutomator2.0 - 控件实现点击操作原理
  2. filp_open/filp_close/vfs_read/vfs_write
  3. Dubbo序列化多个CopyOnWriteArrayList对象变成同一对象的一个大坑!!
  4. Python学习笔记十二
  5. JpaManytoMany
  6. Webpack3 从入门到放弃
  7. haproxy5-ssl
  8. webstorm调试
  9. Windows 运行命令大全,装逼必备哦!
  10. java做图片点击文字验证码