
力扣-283题(Java)-双指针
初始化两个指针 初始化记录结果数组的变量 遍历数组 最终的数组 记录非零元素的位置:我们可以维护一个指针 避免多次遍历:通过两指针交换的方式,避免额外的空间或者时间开销。 处理空数组和全零数组:在代码中应包含边界条件的判断,避免出现异常。
发布日期:2021-05-10 02:26:59
浏览次数:19
分类:精选文章
本文共 1891 字,大约阅读时间需要 6 分钟。
代码解释与优化 - 移动零的算法实现
代码背景与问题理解
提到要优化的代码是否为LeetCode上的问题?如果是其中一个常见的移动零的问题,目标是实现一个高效算法,我们能想到的最优解法复杂度为 O(n),时间复杂度为 O(n),空间复杂度为 O(1)。以下是这个算法的详细解释:
算法思路
我们的目标是通过一次遍历,移除数组中的所有零元素,同时记录输入数组中非零元素的位置,并利用这些位置来构建结果数组。这是一个常用的方法,能够在线性时间内完成任务。
具体步骤如下:
i
和 j
为0。pos
也为0。nums
: - 如果当前元素不是0,则交换
nums[i]
和nums[j]
,并同时交换i
和j
的值。
nums
就是我们希望得到的所有零移动后的数组。代码实现
现来看给出的代码框架:
public class Solution { public void moveZeroes(int[] nums) { int i, pos = 0; for (i = 0; i < nums.length; i++) { // 需要添加具体实现内容 } }}
让我们补全这个代码框架,使其能够实现移动零的功能。
代码补全
public class Solution { public void moveZeroes(int[] nums) { int i = 0, j = 0, pos = 0; // 遍历输入数组,寻找非零元素 while (i < nums.length && nums[i] != 0) { i++; } j = pos; // 初始化记录位置的变量 // 从i位置开始,逐步将非零元素移动到j的位置 while (i < nums.length && j < nums.length) { if (nums[i] == 0) { i++; continue; } // 将nums[i]移动到j的位置 if (j != pos) { nums[j] = nums[i]; } j++; i++; } // 其实这样写可能更高效,或者也可以采用指针交换的方法 // 上面的代码框架可以继续优化 }}
以上代码假设在最初的框架基础上进行了补全。实际上更优的实现方式是使用两指针的交换方式,这样可以在一次遍历中完成。
但需要注意的是,直接在代码中进行交换操作可能会导致数组越界等问题,所以需要进行适当的索引校验。同时,可以考虑在遍历过程中记录非零元素的位置,用来构建结果数组。
代码优化建议
我们可以进一步优化代码的方式:
pos
,用于记录当前应该放置的位置。遍历数组时,每遇到一个非零元素就交换 nums[pos++]
和 nums[i++]
。边界条件与错误处理
- 如果输入数组为空,直接返回。
- 如果输入数组中存在多个零,程序是否能正确处理这些边缘情况?
时间复杂度分析
使用两指针交换的方式,时间复杂度为O(n),空间复杂度为O(1)(常数额外空间)。这是可能的最优解法,因为无法在单次遍历内完成任务。
测试示例
为了验证代码的正确性,可以编写测试用例:
- 测试用例1: 输入数组:
[0,1,0,3,12)
期望输出:[1,3,12,0,0]
- 测试用例2: 输入数组:
[1,2,3,4,0]
期望输出:[1,2,3,4,0]
总结
通过以上分析和代码优化,我们可以发现移动零的算法是一个经典的问题,适合在面试中展现逻辑思维。通过两指针交换的方式能够在O(n)的时间内完成任务,实现高效的代码。
以上是对给定代码的优化和补全,希望对理解和实现移动零算法有所帮助。