题目:给你很多很多正整数,但它们是无序的,找出它们的中位数。
最开始就想说使用快排,先将这些整数进行排序,然后找到中位数,但又想到可能不是面试官想要的答案,于是又采用了其他方法,最终也没完全解决出来。
【经验总结:当面试官问了一个算法题后,如果想不到优化一点的方法,就先把能想到的解决方案告诉他,即使这种方案可能很烂[笑哭],然后再考虑下一步的优化,不要总想着一下就能找到最优的解法,这样最终可能啥也说不出来。】
思路:这题比较好的方法是采用堆,用序列的前(n+1)/2个数建立一个最小堆,然后继续往后遍历,并将每个数与堆顶元素进行比较,如果小于等于堆顶元素,忽略,遍历下一个,如果大于堆顶元素,则将堆顶元素用当前遍历到的元素替换,然后重新调整为最小堆,遍历完成后,堆顶元素即为中位数。 一直保证堆顶是第k小的元素,遍历完成后,堆顶就成了第(n+1)/2小的元素,即为中位数。
代码:
public class Mid {
public static void main(String[] args) {
int[] num = {5,7,6,3,8,1,4};
int n = getMid(num);
System.out.println(n);
}
private static int getMid(int[] num) {
int len =(num.length+1)/2;
for(int i=len/2;i>=0;i--)
adjustHeap(num,i,len-1);
System.out.println(Arrays.toString(num));
for (int j = len; j<num.length; j++) {
if(num[j]>num[0])
{
num[0]=num[j];
adjustHeap(num,0,len-1);
}
}
return num[0];
}
private static void adjustHeap(int[] num, int i, int j) {
int tmp = num[i];
for (int k = 2*i+1; k <=j; k++) {
if(k<j&&num[k]>num[k+1])
k++;
if(num[k]<tmp)
{
num[i]=num[k];
i=k;
}else
break;
}
num[i]=tmp;
}
private static void swap(int[] num, int i, int j) {
int tmp=num[i];
num[i]=num[j];
num[j]=tmp;
}
}
输出: