移动零

283. 移动零

题目描述: 2020/11/18

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

说明:

  1. 必须在原数组上操作,不能拷贝额外的数组。
  2. 尽量减少操作次数。
class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        if not nums:
			return 0
        count = 0
        for i in range(len(nums)):
            if nums[i] == 0:
                count += 1
                continue
            temp = nums[i - count]    
            nums[i - count] = nums[i]
            nums[i] = temp

自己的想法:2020/11/18

快速排序

  1. 找到0,不做改变,把当前不为0的数和第一个出现0的位置进行交换位置,这样虽然0的位置变了,但是不为0的数字按照正常顺序排列

为什么error:

  1. 使用了双重for循环,只能和当前位置进行交换,当变换完之后还是和当前位置进行交换,所以使得出现了很多0

解题思路:

一次遍历
这里参考了快速排序的思想,快速排序首先要确定一个待分割的元素做中间点x,然后把所有小于等于x的元素放到x的左边,大于x的元素放到其右边。
这里我们可以用0当做这个中间点,把不等于0(注意题目没说不能有负数)的放到中间点的左边,等于0的放到其右边。
这的中间点就是0本身,所以实现起来比快速排序简单很多,我们使用两个指针i和j,只要nums[i]!=0,我们就交换nums[i]和nums[j]
请对照动态图来理解:

283_2.gif

时间复杂度: O(n)
空间复杂度: O(1)

两次遍历 : 双指针
我们创建两个指针i和j,第一次遍历的时候指针j用来记录当前有多少非0元素。即遍历的时候每遇到一个非0元素就将其往数组左边挪,第一次遍历完后,j指针的下标就指向了最后一个非0元素下标。
第二次遍历的时候,起始位置就从j开始到结束,将剩下的这段区域内的元素全部置为0。
动画演示:

283_1.gif

时间复杂度: O(n)
空间复杂度: O(1)

作者:wang_ni_ma
链接:https://leetcode-cn.com/problems/move-zeroes/solution/dong-hua-yan-shi-283yi-dong-ling-by-wang_ni_ma/

感想:

​ 时间过长,优化

class Solution:
 def moveZeroes(self, nums: List[int]) -> None:
     """
     Do not return anything, modify nums in-place instead.
     """
     count = 0
     for i in range(len(nums)):
         if nums[i] == 0:
             count += 1 # 记录0有几个
             continue
         if (i > i - count): # 如果i之前没有0,就不交换
             nums[i - count] = nums[i]
             nums[i] = 0
posted @ 2021-04-09 10:44  Tonka  阅读(61)  评论(0编辑  收藏  举报