【发布时间】:2015-07-28 03:31:05
【问题描述】:
今天一位面试官用这样的问题毁了我的生活。
您有一个包含一百万个整数的数组,您需要按余数对它们进行排序。
1. 你不知道他们要除以什么整数。
2. 不能使用 Comparator 等类来提供帮助。
3. 尽可能少循环。
4. 记住要节省内存。
例如
int[] ints = {5434, 3454, 2, 0, 356, 896, 7324, 888, 99, 78365, 111};
int divider = 27;
应该是
int[] int2 = {0, 2, 111, 356, 896, 5434, 7324, 78365, 99, 888, 3454};
我想出的方法 loops = divider / 2.
它可以工作,但如果分频器是 250,那么它会循环 125 次。
public void sortByMod(int[] millionInts, int divideBy) {
long time = System.nanoTime();
int[] b = new int[millionInts.length];
int remainder, remainderMin = 0, remainderMax = divideBy, positionMin = 0, positionMax = millionInts.length - 1;
for (int i = 0; i < millionInts.length;) {
for (int j = 0; j < millionInts.length; j++) {
remainder = millionInts[j] % divideBy;
if (remainder == remainderMin) {
b[positionMin] = millionInts[j];
positionMin++;
i++;
} else if (remainder == remainderMax) {
b[positionMax] = millionInts[j];
positionMax--;
i++;
}
}
remainderMax--;
remainderMin++;
}
System.out.println("time = " + (System.nanoTime() - time));
System.out.println("loopcount = " + remainderMin);
}
我写了另一种方法,它可以在 2 个循环中完成,但读起来很混乱。
它违反了内存限制,但速度非常快。
public void sortByModPro(int[] millionInts, int divideBy) {
int[] range = new int[divideBy];
int[] remainders = new int[millionInts.length];
int[] newArray = new int[millionInts.length];
long times = System.nanoTime();
for (int i = 0; i < millionInts.length; i++) {
remainders[i] = millionInts[i] % divideBy;
range[millionInts[i] % divideBy]++;
}
for (int i = range.length - 1, past = millionInts.length; i >= 0; i--) {
range[i] = past - range[i];
past = range[i];
}
for (int i = 0; i < millionInts.length; i++) {
newArray[range[remainders[i]]] = millionInts[i];
range[remainders[i]]++;
}
System.out.println("time = " + (System.nanoTime() - times));
}
你会如何用 1 个循环来做到这一点?
【问题讨论】:
-
Java 中的数组不能容纳一百万个整数。面试官不知道吗?
-
谷歌快速排序,并用一个小的变化来实现它:而不是直接比较数组中的整数,而是比较它们的余数。
-
@ChetanKinger 当然可以。为什么不能呢?
-
@JBNizet
length在 Java 中的数组存储在int中。 -
是的,所以? 2^31 远大于 100 万。 ideone.com/fGUU89
标签: java arrays performance sorting