题目:

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

  注意,该题目要求不开辟行的数组空间,在原数据上进行操作。

  示例:

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

  说明:

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

自我解答:

  思路1:如同冒泡算法那样,用两个for循环进行遍历,将0依次移动到列表最后面。

  缺点:复杂度太高,n^n,上传答案时会报错。

  思路2:for循环遍历数组,当该数为0时,remove移除该数,

    在这里有两个python知识点。

  原本,我是希望先把所有的0删除后,再往后面添加同样数量的0,但是,发现删不掉0的情况

list1 = [0,2,0,0,8,0,8,0,1]
class Solution2:
def moveZeroes(self, nums):
for i in nums:
if i ==0:
nums.remove(i)
# nums.append(0)
print(nums) s = Solution2()
s.moveZeroes(list1)
#[2, 8, 8, 0, 1]

  百度了一番发现了其中的奥秘:

  for循环原理

  python中for循环是遍历所有nums下标,然后根据下标遍历列表。

  当列表边遍历边删除的时候,会出现漏遍历的情况,当列表中的数字被删除时,后面的数字会跟上,他们的下标也会跟着改变,如

list1=[1,2,3,4,5,6]
for i in list1:
remove(i)
#[2,4,6]

  因为删除了1,所以2代替了原来1的位置,for循环就会寻找现在列表中的2位置是谁,很显然2是数字3.

  但是又有一个问题,难道在遍历了6之后还有3个下标没有遍历会怎么处理呢。

  这就涉及到for循环的内部原理,其中有__next__方法就是获取下一个元素,当获取不到时就会报错,然后内部处理异常,停止取值。

  remove原理

  但光是这样的话,上述代码最后执行的结果不就是[2,0,8,8,0,1]吗。

  原来remove的删除原因是删除当前列表中第一个匹配的值,所以当遍历到后面的0时会删除前面跳过的0,但是遍历到的0总是比较少的,所以最后总会漏掉1到2个。

  解决方法:

  1.这个方法不是很完美,因为方法不变,只是边删除0边在后面添加0,这就使得原先没有遍历结束的下标全部遍历,所以不妨换一个角度想。

  我们每遍历到一个0就获得删除一个0的机会(remove),每删除一个0就会添加一个0,所以列表总长度不变,最后原先列表遍历结束后,就会遍历添加进去的0,直到遍历结束。

  或者理解为保证列表长度不变的情况下,尽可能的删掉队列中所有的0,那这些0到哪里去了呢,显然就是append的哪些:

list1 = [0,2,0,0,8,0,8,0,1]
class Solution2:
def moveZeroes(self, nums):
for i in nums:
if i ==0:
nums.remove(i)
nums.append(0)
print(nums)
#[2, 8, 8, 1, 0, 0, 0, 0, 0]

  2,从后往遍历。

  这种方法适用于任何边循环边改变列表元素的问题,使用切片中默认值的方式:

class Solution:
def moveZeroes(self, nums: List[int]) -> None:
for i in nums[::-1]:
if i==0:
nums.remove(i)
nums.append(0)

  添加的0和剔除的0在总列表的最后,不会影响for循环中即将遍历的值.

官方解答:

  这个题目的标签是数组与双指针。可以这么做:

  定义一个长指针和一个短指针。

  长指针用来判断列表中的0元素直到最后,短指针则用来记录非0的值到列表中。

  最后再在短指针的最后将所有的值改成0,实现该功能。

list1 = [0,2,0,0,8,0,8,0,1]
class Solution:
def moveZeroes(self, nums):
long_t = 0
short_t = 0
while long_t < len(nums):
if nums[long_t]!=0:
nums[short_t] = nums[long_t]
long_t +=1
short_t +=1
else:
long_t +=1
while short_t <len(nums):
nums[short_t] = 0
short_t += 1
print(nums) #[2, 8, 8, 1, 0, 0, 0, 0, 0]

  python中实现指向数组的指针都可以使用这种方法,这种方法在执行时间的角度来讲也比较合理。

283.移动零 关于列表list与remove原理*****(简单)的更多相关文章

  1. 前端与算法 leetcode 283. 移动零

    目录 # 前端与算法 leetcode 283. 移动零 题目描述 概要 提示 解析 解法一:暴力法 解法二:双指针法 算法 传入[0,1,0,3,12]的运行结果 执行结果 GitHub仓库 # 前 ...

  2. 【Leetcode】【简单】【283. 移动零】【JavaScript】

    题目描述 283. 移动零 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12]输出: [1,3,12,0,0] 说 ...

  3. 在Python的列表中利用remove()方法删除元素的教程

    在Python的列表中利用remove()方法删除元素的教程 这篇文章主要介绍了在Python的列表中利用remove()方法删除元素的教程,是Python入门中的基础知识,注意其和pop()方法的区 ...

  4. Java实现 LeetCode 283 移动零

    283. 移动零 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必 ...

  5. 【LeetCode】283.移动零

    283.移动零 知识点:数组:双指针: 题目描述 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例 输入: [0,1,0,3,12] 输出: [1, ...

  6. Android零基础入门第11节:简单几步带你飞,运行Android Studio工程

    原文:Android零基础入门第11节:简单几步带你飞,运行Android Studio工程 之前讲过Eclipse环境下的Android虚拟设备的创建和使用,现在既然升级了Android Studi ...

  7. 1102: 零起点学算法09——继续练习简单的输入和计算(a-b)

    1102: 零起点学算法09--继续练习简单的输入和计算(a-b) Time Limit: 1 Sec  Memory Limit: 520 MB   64bit IO Format: %lldSub ...

  8. python(leetcode)-283移动零

    给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必须在原数组上操作, ...

  9. LeetCode(283. 移动零)

    问题描述 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必须在原数 ...

随机推荐

  1. SpringBoot 全局异常配置

    在日常web开发中发生了异常,往往是需要通过一个统一的异常处理来保证客户端能够收到友好的提示. 一.默认异常机制 默认异常处理(SpringBoot 默认提供了两种机制,一种是针对于web浏览器访问的 ...

  2. 让人又爱又恨的this

    this是个神奇的东西, 既可以帮助我们把模拟的类实例化. 又可以在事件绑定里准确指向触发元素. 还可以帮助我们在对象方法中操作对象的其他属性或方法. 甚至可以在使用apply.call.bing.f ...

  3. 牛客小白月赛18 Forsaken喜欢数论

    牛客小白月赛18 Forsaken喜欢数论 题目传送门直接点标题 ​ Forsaken有一个有趣的数论函数.对于任意一个数xxx,f(x)f(x)f(x)会返回xxx的最小质因子.如果这个数没有最小质 ...

  4. 无法用排他锁锁定该数据库,以执行该操作。 (Microsoft SQL Server,错误: 5030)

    ALTER DATABASE Test_DB modify name = Howie --更改数据库名 EXEC sp_renamedb 'Howie' , 'Howie_Wee' --更改数据库名 ...

  5. Spark内核| 调度策略| SparkShuffle| 内存管理| 内存空间分配| 核心组件

    1. 调度策略 TaskScheduler会先把DAGScheduler给过来的TaskSet封装成TaskSetManager扔到任务队列里,然后再从任务队列里按照一定的规则把它们取出来在Sched ...

  6. Nginx 负载均衡算法

    Nginx 负载均衡算法 1.轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务,如果后端某台服务器死机,自动剔除故障系统,使用户访问不受影响. upstream tomcat_server { ...

  7. [LOJ 6288]猫咪[CF 700E]Cool Slogans

    [LOJ 6288]猫咪[CF 700E]Cool Slogans 题意 给定一个字符串 \(T\), 求一个最大的 \(K\) 使得存在 \(S_1,S_2,\dots,S_k\) 满足 \(S_1 ...

  8. HTML连载20-并集选择器&兄弟选择器

    一.并集选择器 1.作用:给所有的选择器选中的标签设置属性. 2.格式: 选择器1,选择器2{ 属性:值: } 3.例如: .abc1,#abc2{ color:red; } .......省略代码. ...

  9. vue项目打包之后样式错乱问题,如何处理

    最近公司做的这个项目,要大量修改element里面的css样式,所以项目打包之后 会出现样式和本地开发的时候样式有很多不一样,原因可能是css加载顺序有问题,样式被覆改了. 所以在mian.js里面这 ...

  10. Vue.js 源码分析(二十五) 高级应用 插槽 详解

    我们定义一个组件的时候,可以在组件的某个节点内预留一个位置,当父组件调用该组件的时候可以指定该位置具体的内容,这就是插槽的用法,子组件模板可以通过slot标签(插槽)规定对应的内容放置在哪里,比如: ...