前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >我对一道常考面试题的详细分析

我对一道常考面试题的详细分析

作者头像
double
发布2020-07-06 14:28:51
7510
发布2020-07-06 14:28:51
举报
文章被收录于专栏:算法channel

移动零

题目

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

示例:

输入: [0,1,0,3,12]

输出: [1,3,12,0,0]

说明:

  1. 必须在原数组上操作,不能拷贝额外的数组。
  2. 尽量减少操作次数

分析

必须在原数组上操作,不能拷贝额外的数组;同时尽量减少操作次数,说白了就是想叫我们写出更好的算法。

如何分析?

观察

输入: [0,1,0,3,12]

输出: [1,3,12,0,0]

整个过程就是0元素不断后移,非零元素不断前移的过程,所以算法每步操作的目标便是:逐渐达成这个分布规律

怎样优化操作?

假设两个指针slowfast分别指向连续零区间的第一个0,最后一个0的后一个位置,如下图所示:

那么,fast-slow 正是索引从0~fast区间范围内0元素的个数。

fast指向下一个元素:

若打问号元素为0,根据每步操作的目标是非零元素前移,零元素后移。所以迭代到此处时它已经为0元素,所以至少肯定不用前移,那么就保持原地不动。

若打问号的元素取值非0,根据每步操作的目标是非零元素前移,零元素后移。因为slow~fast这块都为0,所以为了目标,非零元素要和第一个0交换,这样不就实现非零元素前移,零元素后移的目标了吗

交换后:

你看确实前进一步了吧。

求解代码

以上分析过程就是此问题的一个中间状态的操作分析,是从第i次迭代状态到第i+1次迭代状态的变化过程。

有了这个状态更新方程,因此就会很自然的写出下面的代码:

代码语言:javascript
复制
class Solution(object):
    def moveZeroes(self, nums):
        fast,slow=0,0 # 分别指向连续零区间的最右侧、最左侧
        while fast<len(nums):
            # if nums[fast]==0 do nothing 
            if nums[fast]!=0:
                # if fast == slow shows zero isn't found yet
                if fast > slow:# zero exists
                    nums[slow], nums[fast] = nums[fast], 0
                slow += 1
            fast += 1   

S1,设定两个指针初始分别指向第一个元素:

S2,第一个元素等于0,仅fast前进1步:

S3, 下一次迭代时,fast指向元素不为0,则交换:

同时slowfast同时都前进一步:

S4,此时元素等于0,此情况重复步骤S2,因此重复上面操作。

依次类推,罗列出中间的各个状态:

fast到头,程序结束。

可以看到slow指向连续零区间的第一个0,fast指向连续零区间的最后一个0的后一个位置。

这与文章中分析中间状态的过程一脉相承,验证分析过程是准确的。

Day1-Day35 刷题总结的思维导图

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员郭震zhenguo 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 移动零
    • 题目
      • 分析
        • 求解代码
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档