Java面试问题是:
不使用临时缓冲区,将0和1与数组分开,将所有0放在左边,将1放在右边。将结果打印为字符串。例如,给定{0,1,1,0,0,1},输出为“000111”。
答案是:
public class ZeroOneSeparator {
public static void zeroOneSeparator(int[] inputArr){
// for each index, store number of 1's up to the index
for (int i = 1; i < inputArr.length; i++) {
inputArr[i] = inputArr[i-1] + inputArr[i];
}
// This is the "magical math" block I don't understand.
// Why does this "work"?
for (int i = inputArr.length - 1; i > 0; i--) {
if (inputArr[i] > 0) {
inputArr[i-1] = inputArr[i] - 1;
inputArr[i] = 1;
} else {
inputArr[i-1] = 0;
}
}
for (int i = 0; i < inputArr.length; i++) {
System.out.print(inputArr[i]);
}
}
public static void main(String[] args) {
int[] inputArr1 = {1,0,1,0,1,1};
ZeroOneSeparator.zeroOneSeparator(inputArr1);
System.out.println();
int[] inputArr2 = {1,1,1,0,0,0,0,0,0,1};
ZeroOneSeparator.zeroOneSeparator(inputArr2);
int[] inputArr3 = {}; // intentionally empty
System.out.println();
ZeroOneSeparator.zeroOneSeparator(inputArr3);
int[] inputArr4 = {0,0,0,0,0,0};
System.out.println();
ZeroOneSeparator.zeroOneSeparator(inputArr4);
int[] inputArr5 = {0,1,0,1,0,1,0,1};
System.out.println();
ZeroOneSeparator.zeroOneSeparator(inputArr5);
int[] inputArr6 = {1,1,1,1,1,1,0,0,0,0,0};
System.out.println();
ZeroOneSeparator.zeroOneSeparator(inputArr6);
}
}
我使用调试器逐步完成了这段代码,但我仍然不明白为什么会这样。有人可以带我走过吗?
答案 0 :(得分:7)
让我们试一试看看发生了什么。假设我们有以下数组:
0 1 1 0 1 1 0 0
第一个循环(如注释所指定的)计算到目前为止看到的1的总数,其中每个1增加计数,每个0使它保持相同。所以对于我们的数组,我们最终得到了这个:
0 1 2 2 3 4 4 4
请注意,数组的最后一个元素现在是4,这是1的总数。我们在下一个循环中使用这个事实。
我们从最后一个元素开始,检查它是否大于0.如果是,则我们用1替换该元素,然后将该计数减1并将其分配给前一个元素。我们继续这样做,随着时间的推移填充1,直到计数达到0.此时,我们将遇到的每个元素设置为0。
这里真正发生的是,一旦我们知道有多少1,我们可以从数组的末尾“倒计时”,填入1的数量。此时,我们知道其余元素必须为0,因此我们可以将其余元素设置为0。
在视觉上,它看起来像这样(“当前元素”被[]的包围)
0 1 2 2 3 4 4 [4] ->
0 1 2 2 3 4 [3] 1 ->
0 1 2 2 3 [2] 1 1 ->
0 1 2 2 [1] 1 1 1 ->
0 1 2 [0] 1 1 1 1 ->
0 1 [0] 0 1 1 1 1 ->
0 [0] 0 0 1 1 1 1 ->
0 0 0 0 1 1 1 1
请注意,以这种方式观看时,“倒计时”似乎非常明显。
答案 1 :(得分:2)
由于您在最后一个索引处的数组中计数为1,因此您只需从后面循环并将其替换为1。在代码中完成的技巧是,它减少了1的计数并将其存储在每个步骤中的前一个数组元素中,以便在下一步中,它知道当前元素是0还是1.它运行良好即使在所有1或几乎所有1的情况下(数组中只有一个0),因为在修改索引0处的元素时剩下的1的计数恰好是正确的数字。
就个人而言,我会记录1的计数,得出0的计数并使用2个循环来打印/设置数组中的数字。
答案 2 :(得分:1)
首先 for 循环计算每个项目左侧有多少个1。如果输入为{0,1,1,0,0,1}
,则作为计数的结果,输入数组变为{0,1,2,2,2,3}
。
最后一个索引3表示列表中有三个1。第二个 for 循环反向遍历列表,并为最后三个项目标记为1。