LeetCode #27: Remove Element
β’ 452 words β’ 3 min β’ updated
The original problem states:
remove all occurrences of val in
numsin-place
Instead, I opted for allocating a new list.
Elegant #
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
a = [el for el in nums if el != val]
nums[:] = a # OR nums[0:len(a)] = a
return len(a)You might as well get rid of a:
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
nums[:] = [el for el in nums if el != val]
return len(nums)Optimal #
Can we get by without allocating a new list?
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
n = 0
for el in nums:
if el != val:
nums[n] = el
n += 1
return nOr we could always use indexes, if you prefer:
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
n = 0
for i, el in enumerate(nums):
if el != val:
if i != n: # avoid unnecessary assignments
nums[n] = el
n += 1
return nYou really like C/C++1?
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
n = 0
for i in range(len(nums)):
if nums[i] != val:
if i != n: # avoid unnecessary assignments
nums[n] = nums[i]
n += 1
return n
The delete way
#
We could also drop elements from the list.
However, to keep the order stable, we need to start from the end.
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
for i, el in reversed(list(enumerate(nums))):
if el == val:
del nums[i]Note that we cannot use reversed with enumerate directly:
>>> enumerate([3,4,5])
<enumerate object at 0x1056d1b70>
>>> list(enumerate([3,4,5]))
[(0, 3), (1, 4), (2, 5)]
>>> reversed(enumerate([3,4,5]))
Traceback (most recent call last):
File "<python-input-2>", line 1, in <module>
reversed(enumerate([3,4,5]))
~~~~~~~~^^^^^^^^^^^^^^^^^^^^
TypeError: 'enumerate' object is not reversibleThere’s no need to memorize that.
Heck, there’s no need to even remember that reversed2 exists:
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
for i, el in list(enumerate(nums))[::-1]:
if el == val:
del nums[i]New:
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
p = 0
for i, num in enumerate(nums):
## 1 2 2 3
## 2
nums[p] = nums[i]
if num != val:
p += 1
return p-
In Python, there’s generally no need to use
for i in range(len(v)). In general, it’s more elegant to usefor i, el in enumerate(v). Even if you don’t care about the element:for i, _ in enumerate(v). If you don’t care about the index:for el in vwhich is simpler thanfor _, el in enumerate(v). ↩︎ -
[::-1]slicing reverses a list. ↩︎