本文共 1527 字,大约阅读时间需要 5 分钟。
移动零问题是一道经典的数组操作题目,要求将数组中的所有零移动到数组的末尾,同时保持非零元素的相对顺序。解决这个问题的方法有多种,这里将介绍两种常见的解法,并分析它们的优缺点。
这种方法的思路是先遍历数组,找到所有零元素。然后,每次找到一个零时,将其删除,并在数组的末尾添加一个零。这种方法虽然简单,但可能需要多次遍历数组,导致时间复杂度较高。具体步骤如下:
count
为0。nums.pop(count)
删除该零,并调用nums.append(0)
将其添加到末尾。count
加1,继续遍历下一个位置。这种方法的代码实现如下:
class Solution: def moveZeroes(self, nums: List[int]) -> None: count = 0 n = len(nums) while count < n: if nums[count] == 0: nums.pop(count) nums.append(0) count += 1
优点:代码简洁,易于理解。缺点:当数组中有多个连续的零时,可能需要多次数组操作,导致时间复杂度较高。
这种方法采用双指针的方式,左指针记录当前处理的位置,右指针扫描数组中的非零元素。当右指针找到非零元素时,将其与左指针位置的元素交换,然后左指针前进。这样可以保证所有非零元素按原来的顺序排在前面,零则被移动到末尾。这种方法的时间复杂度为O(n),空间复杂度为O(1),非常高效。具体步骤如下:
left
和right
都为0。right
指针从左到右遍历数组。nums[right]
不为零时,将nums[left]
和nums[right]
交换,然后left
加1。right
继续向右移动,直到遍历完整个数组。这种方法的代码实现如下:
class Solution: def moveZeroes(self, nums: List[int]) -> None: left = right = 0 l = len(nums) while right < l: if nums[right] != 0: nums[left], nums[right] = nums[right], nums[left] left += 1 right += 1
优点:时间复杂度为O(n),空间复杂度为O(1),非常高效。缺点:需要交换元素位置,可能导致数组元素位置改变,但这并不会影响最终的数组元素内容。
两种方法都可以在原数组上操作,没有额外的数组拷贝。为了进一步优化,可以在双指针方法中记录零的数量,并在最后一次遍历时直接添加零到末尾。这可以减少一次遍历的时间。具体步骤如下:
zero_count
为0。zero_count
个零。这种优化可以将时间复杂度从O(n)降低到O(n),并减少额外的操作次数。
两种方法各有优缺点,选择哪种方法取决于具体的需求。双指针方法在时间和空间上都更为高效,适合大多数情况。而逐个处理零的方法则简单易懂,适合处理较小规模的数组或需要多次修改数组的场景。
转载地址:http://skog.baihongyu.com/