面试题四十:数组中最小的k个数
方法一:先排序后寻找前k个数;
方法二:受面试题三十九,寻找超过一半的数的启发,只把里面的middle改成k-1就行;
void HalfNum( int [ ] Array ,int k){ int start=0; int end=Array.length-1; int index=Patition(Array ,start ,end); //不求排序,只求不断向中间靠近 while(index!=k){ if(index>k){ end=index-1; } else start=index+1; index=Patition(Array ,start ,end) } for(int i=0;i<k;i++) { System.out.print(Array[i]+" "); } System.out.println(); } int Patition( int [] a,int be,int end){ int inter=a[be];//把起始位置作为主元 int L=be+1; int R=end; int b; while(L<=R)///数组都遍历完了即R与L交错时停止循环 { while(L<=R&&inter>=a[L]) L++; while(L<=R&&inter<a[R]) R--; if(L<R) {b=a[L]; a[L]=a[R]; a[R]=b;} ///交换位置,把比主元大的放后面 ,比主元小的放前面 } a[be]=a[R];a[R]=inter;///交换位置把主元放进去作为间隔 return R; }
方法三:适合处理**海量的数据**,创建一个大小为k的容器,首先填满,再寻找最大值,比较替换;
void MinK(int[] Array,int k) { int[] A_k = new int[k]; //K堆的大小开辟空间 int i=0; //填满K堆 while(i<k){ A_k[i] = Array[i]; i++; } BuildHeap(A_k);//建堆 while(i<Array.length) { if(Array[i]<A_k[0]) { A_k[0]=Array[i]; Heapify(0, A_k);/// 调堆 } i++; } for(int j=0;j<k;j++) { System.out.print(A_k[j]+" "); } System.out.println(); } // 建堆,二叉树用数组表示:根节点下标为n=0;左子树为2n+1,右子树为2n+2;求父节点则为(n-1)/2 public static void BuildHeap(int[] Array) { //找到最后一个非叶子节点开始,自底向上调整 for(int i=Array.length/2-1;i>=0;i--) Heapify(i, Array); } // 调堆,就是把最大值最为根节点i //以i为根节点建立大顶堆 public static void Heapify(int i,int[] Array){ int left = i*2+1;//左孩子 int right = i*2+2;//右孩子 //寻找最大值下标 int biggest = i; if(left < Array.length && Array[left]>Array[i] biggest = left; if(right<Array.length && Array[biggest]<Array[right]) biggest = right; //如果根节点就是最大,那么下面的子树就不用管 if(i == biggest) return; //否则两个值交换后,调整下面交换后的堆 int temp = Array[i]; Array[i] = Array[biggest] Array[biggest] = temp; Heapify(biggest, Array); }
浪波激泥