今天去某D轮互联网公司面试,被面试官问到一个和算法有关的问题:从一亿长度的整形数组中取出最大的六个数。
当时第一印象是使用排序算法,然后取最大六个。明显面试官不满意,我也知道肯定不是这么简单的问题,但当时脑袋空白想不到什么高效的方法。在回去的路上开始思考这个问题,真正静下来后感觉问题变简单了,很快想到了一个思路。
问题的关键点在于只需要取最大的六个,于是这样一个思路就出来了。
第一步. 直接初始化一个长度为6的目标数组,直接从源数组中取出前六个使用排序算法升序排序,然后放到目标数组中。
第二步. 从源数组的第七位开始遍历,拿源数组的第七位与目标数组的最小数比较。
第三步. 如果上面比较结果源数组第七位小于等于目标数组最小数,则直接舍弃开始遍历源数组第八位,反之则将源数组第七位代替目标数组最小数,然后继续与目标数组最小数比较,依次循环到目标数组最大数。
第四步. 依第三步逻辑依次遍历源数组直至结束,最终目标数组即为结果。
结论:因为只需要只最大六位数,所以第三步的循环最多只会6 * 6 = 32次。与源数组的循环次数可以直接忽略不计。最终实现遍历一次源数组的次数就能实现找出最大六位数。
总结:需要静下心来思考问题,现场思考能力欠缺。
测试代码如下:
import java.util.Arrays;
import java.util.Random;
/**
* 从很大的数组中取出最大六位数
*/
public class MaxNumber {
public static void main(String[] args) {
// 初始化长度为1000的源数组
int[] sources = new int[1000];
int length = sources.length;
for(int i = 0; i < length; i++) {
sources[i] = new Random().nextInt(10000);
System.out.println(sources[i]);
}
// 初始化目标数组,并将源数组前六位放入目标数组
int[] result = new int[6];
int resultLength = result.length;
for(int i = 0; i < resultLength;i++) {
result[i] = sources[i];
}
// 使用排序算法对目标数组进行排序
Arrays.sort(result);
// 从第七位开始遍历源数组
for(int i = 6; i < length; i++) {
// 源数组与目标数组遍历比较
for(int x = 0, y = result.length; x < y; x++) {
// 源数组小于等于目标数组直接舍弃
if(sources[i] <= result[x]) {
break;
}
// 当前目标数组前移(若当前目标数组为最小数则直接舍弃),源数组代替当前目标数组,
if(x > 0) {
result[x - 1] = result[x];
}
result[x] = sources[i];
}
}
// 输出目标数组
for(int i = 0; i < resultLength; i++) {
System.out.println("result" + i + " : " + result[i]);
}
}
}
测试结果: