这个题解决了两个疑问:
1.for循环中不能用原地法将列表中的特定元素删除干净,但while循环可以(解释)。
2.双指针的思想很巧妙
问题描述
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1:
给定 nums = [3,2,2,3], val = 3,
函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。示例 2:
给定 nums = [0,1,2,2,3,0,4,2], val = 2,
函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
注意这五个元素可为任意顺序。来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-element
思路与提示
思路
如果将列表中值为val的元素直接pop或者remove出,很容易就可以实现。但是操作的时候发现用for 循环无法将列表中的特定元素删除干净。
官方提示
1.Try two pointers.
2.Did you use the property of “the order of elements can be changed”?
3.What happens when the elements to remove are rare?
代码
while 循环
class Solution(object):
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
while val in nums:
nums.remove(val)
return len(nums)
双指针
1.代码:
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
if not nums:return 0
slow = 0
n = len(nums)
fast = n - 1
while slow < fast:
while slow < fast and nums[slow] != val:
slow += 1
while slow < fast and nums[fast] == val:
fast -= 1
nums[slow],nums[fast] = nums[fast],nums[slow]
slow += 1
fast -= 1
res = 0
#print(nums,slow,fast)
#return fast + 1
for i in range(n):
if nums[i] == val:
return res
res += 1
#作者:powcai
#链接:https://leetcode-cn.com/problems/remove-element/solution/yi-chu-yuan-su-by-powcai/
#来源:力扣(LeetCode)
#著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2.解释:
以题中的 nums = [3,2,2,3], val = 3 为例。
开始时 i 和 j 都指向下标 0 位置:
此时 j 指向的元素为 val,所以把 j 右移动 1 位:
此时,开拓者 j 找到了一个非 val 元素,那么就赋值给 i 吧:
赋值以后,我们得到了一个新的序列 [2, 2, 2, 3],我们可以得知:
– i 指向的元素一定不是 val,因为它是从 j 指向的元素赋值得来的,j 指向非 val 元素才会进行赋值
– j 指向的元素一定不是非 val???
这样一来,i 和 j 都完成了本轮使命,继续前进!
因此每次交换以后,我们都同步增长双指针,令 i = i + 1,j = j + 1:
此时 j 又指向了一个非 val 元素,继续赋值:
因为本次 i 与 j 指向元素相同,所以赋值后序列没有改变。赋值操作后,我们继续同步增长双指针:
此时 j 指向了一个 val 元素,无法进行赋值操作,继续增长 j,令 j = j + 1:
此时我们发现 j 超出数组范围了,循环结束。[2, 2, 2, 3] 即为我们最终所求结果,而红色部分即为新数组长度,长度为 len(nums) - (j - i)。作者:jalan
链接:https://leetcode-cn.com/problems/remove-element/solution/tu-jie-shuang-zhi-zhen-leetcode-27-yi-chu-yuan-su-/
来源:力扣(LeetCode)
总结
1.两种方法的时间复杂度应该都是O(n)。但在while循环中,数组增删都比较耗资源(可以了解一下pop这个方法内部的实现又有多少复杂度)。
2.双指针似乎有更优雅的写法
来源:CSDN
作者:weixin_45182000
链接:https://blog.csdn.net/weixin_45182000/article/details/103473225