Java中将零移至数组末尾

💡 原文中文,约2200字,阅读约需6分钟。
📝

内容提要

本文介绍了在Java中将零移动到数组末尾的两种方法,一种使用额外的数组,另一种在原数组上操作,复杂度均为O(n)。

🔎

延伸解读

两种方法的空间复杂度差异

使用额外数组的方法需要创建一个与输入等长的新数组,因此空间复杂度为O(n)。而就地方法仅使用一个非零指针idx,在原数组上直接操作,空间复杂度为O(1)。当处理大规模数据或内存受限时,就地方法能显著减少内存占用,但两种方法的时间复杂度均为O(n),性能差异不大。

就地方法的实现细节与注意事项

就地方法通过一次遍历将非零元素依次移到数组前部,同时用idx记录下一个非零元素应放置的位置。遍历结束后,从idx到数组末尾填充零。需要注意的是,在移动非零元素时,可能会覆盖尚未处理的元素,但由于idx始终小于等于当前遍历索引,不会丢失数据。

最坏情况下的性能表现

当输入数组全为零时,就地方法中的idx指针在遍历过程中不会移动,因此后续的while循环需要再次遍历整个数组来填充零。尽管如此,总操作次数仍与数组长度成正比,时间复杂度保持O(n)。这表明该算法在各种输入下都具有稳定的线性性能。

❓

Q&A

Java中如何将数组里的零移动到末尾并保持非零元素顺序?

有两种方法:一是使用额外数组,遍历原数组,将非零元素依次放入新数组,剩余位置默认为零;二是就地操作,用非零指针idx,遍历数组时将非零元素移到前面,最后用零填充剩余位置。两种方法都保持非零元素的相对顺序。

移动零到数组末尾的两种方法的时间和空间复杂度分别是多少?

使用额外数组的方法时间复杂度为O(n),空间复杂度为O(n);就地操作的方法时间复杂度为O(n),空间复杂度为O(1)。

为什么使用额外数组的方法不需要显式地用零填充新数组?

因为在Java中,int[]数组的元素默认初始化为零,所以创建新数组后,未赋值的元素自动为零,无需额外填充。

就地移动零的算法具体是如何工作的?

使用一个非零指针idx,初始为0。遍历数组,当遇到非零元素时,将其赋值到array[idx]并递增idx。遍历结束后,从idx位置到数组末尾用零填充。这样非零元素按原顺序移到前面,零全部移到末尾。

在测试数组相等时,为什么应该使用assertArrayEquals而不是assertEquals?

因为assertEquals比较的是数组对象的引用,而不是内容;assertArrayEquals会逐个比较数组元素,确保内容相同。

就地移动零的方法在最坏情况下的性能如何?

最坏情况是数组全为零,此时非零指针idx在遍历后仍为0,后续while循环会再次遍历整个数组填充零。但总体时间复杂度仍为O(n),因为遍历次数是常数次。

🏷️

标签

➡️

继续阅读