Codingbat zeroFront Java题解修复及Stream API实现咨询
zeroFront 题目说明
给定来自CodingBat平台的 zeroFront 题目,题目要求如下:
返回与给定数组包含完全相同数字的数组,重新排列后所有0都集中在数组开头。
非零数字的顺序不做要求,例如{1, 0, 0, 1}处理后为{0 ,0, 1, 1}。可以修改传入的原数组后返回,也可以返回新构建的数组。
测试用例如下:
zeroFront([1, 0, 0, 1]) → [0, 0, 1, 1] zeroFront([0, 1, 1, 0, 1]) → [0, 0, 1, 1, 1] zeroFront([1, 0]) → [0, 1]
问题描述
编写的如下解题代码在部分场景下会抛出ArrayIndexOutOfBoundsException异常:
public int[] zeroFront(int[] nums) { if (nums.length == 0) { return nums; } int[] zeroFront = new int[nums.length]; int zeroCounter = 0; for (int i = 0; i < zeroFront.length; i++) { if (nums[i] == 0) { zeroCounter++; } } for (int i = 0; i < zeroCounter; i++) { zeroFront[i] = 0; } for (int i = 0; i < nums.length; i++) { if (nums[i] != 0) { zeroFront[zeroCounter + i] = nums[i]; } } return zeroFront; }
需要解答两个问题:
- 如何修复当前编写的解题代码,解决数组索引越界问题?
- 如何使用Stream API实现该题目的解法?
问题解答
1. 原代码索引越界修复
越界原因
填充非零元素的循环中,错误使用zeroCounter + i作为目标数组的写入索引:i是遍历原数组的下标,取值范围为0 ~ nums.length-1,当遍历到原数组后半段的非零元素时,计算出的索引会超出目标数组的最大下标,触发越界异常。
修复后代码
单独维护非零元素的写入下标,初始值等于统计得到的0的个数,每写入一个非零元素就将下标自增:
public int[] zeroFront(int[] nums) { if (nums.length == 0) { return nums; } int[] zeroFront = new int[nums.length]; int zeroCounter = 0; for (int i = 0; i < nums.length; i++) { if (nums[i] == 0) { zeroCounter++; } } for (int i = 0; i < zeroCounter; i++) { zeroFront[i] = 0; } int nonZeroWriteIdx = zeroCounter; for (int i = 0; i < nums.length; i++) { if (nums[i] != 0) { zeroFront[nonZeroWriteIdx++] = nums[i]; } } return zeroFront; }
2. Stream API 实现方式
核心思路是将数组元素拆分为「0元素流」和「非0元素流」,按顺序拼接两个流后转换为数组即可:
import java.util.Arrays; import java.util.stream.IntStream; public int[] zeroFront(int[] nums) { return IntStream.concat( Arrays.stream(nums).filter(num -> num == 0), Arrays.stream(nums).filter(num -> num != 0) ).toArray(); }
内容的提问来源于stack exchange,提问作者Evgeniy
相关产品推荐
相关产品推荐

