[LeetCode] TIL LeetCode: 27, 26
27. Remove Element
Problem type - Array
🧩 Problem
🎯 Strategy
Understand the concept
Read the given instructions carefully.
Two arguments are given: an integer array nums
and an integer val
.
The val
should be removed from the nums
array, and the removal process should be in place.
The important note is that we are returning the first k
elements of the num
array, which derive our answer as a single integer.
The k
is the length of the changed array or the index as we change the array in place.
Basic approach
remove()
approach
Let’s use a Python library to simplify and get used to this concept.
The remove()
function is indeed not an in-place approach, but we can make simple code as below:
def removeElement(self, nums: List[int], val: int) -> int:
while val in nums:
nums.remove(val)
This could be a one-liner code and shows the power of the Python library. But it takes much more time and is not an in-place algorithm.
The time complexity is O(n^2)
because the .remove()
operation has a time complexity of O(n)
. And the while loop has a time complexity of O(n)
, hence the overall time complexity is O(n^2)
.
The space complexity is O(1)
, since it doesn’t create any additional data structures or use extra memory.
Two pointer approach
For loop and pointer
Although the above code does the job, there are better answers than this one.
What we can do instead is use a pointer to achieve the same goal. The picture below is the typical two-pointer structure in the algorithm.
We use the same technique above while putting the pointer k = 0
and looping through the nums array with for-loop
.
We will skip if the number in the nums
array equals val
. If the number in the nums
array is not equal to val
, we change the value.
In this case of 0, 1
, we assigned each value in-place. But when it comes to k = 2
, k didn’t go further, but the num
goes further the list.
When the num
reaches 3
, it assigns 3
to the current k
’s place. This is the logic for the pointer approach.
def removeElement(self, nums: List[int], val: int) -> int:
k = 0
for num in nums:
if num != val:
nums[k] = num
k += 1
return k
As the loop finishes, the k
goes to the expected index, or we can say k == expectedNums.length
.
The time complexity is O(n)
because we use a for-loop to iterate through the nums
array.
The space complexity is O(1)
because the code operates in place, modifying the nums
array without creating a new data structure.
📌 Thoughts
I was trying hard to get exactly the same output in example 2, but it turns out I didn’t read the question carefully.
The custom judge part mentions that assert k
is the length of the expected array and sort()
the nums, so the order of numbers doesn’t really matter in this problem.
💻 Solution
.remove()
approach / not in-place
def removeElement(self, nums: List[int], val: int) -> int:
while val in nums:
nums.remove(val)
Two-pointer approach / in-place
def removeElement(self, nums: List[int], val: int) -> int:
k = 0
for num in nums:
if num != val:
nums[k] = num
k += 1
return k
26. Remove Duplicates from Sorted Array
Problem type - Array
🧩 Problem
🎯 Strategy
Concept of the problem
Given conditions
Given that the array is nums
, we need to remove the recurrent numbers in the array. The array is sorted in ascending order, and we need to use the in-place
algorithm to derive the k
- the first k elements of nums
that are not replicated.
Basic approach
set()
approach
Similar to the previous problem, we can solve the current situation with the Python library but not in an in-place manner.
def removeDuplicates(self, nums: List[int]) -> int:
nums[:] = set(nums)
return len(nums)
Notice the set()
method cuts off the duplicated data.
original: [0, 0, 1, 1, 1, 2, 2, 3, 3, 4]
modified: [0, 1, 2, 3, 4]
The time complexity is O(n)
since converting the array nums
to a set has a time complexity of O(n)
.
The space complexity is O(n)
, because the set()
creates and stores the modified array.
Two pointer approach
For-loop and pointer
The two-pointer approach is very similar to the previous problem. The difference is the usage of the index.
def removeDuplicates(self, nums: List[int]) -> int:
k = 0
for num in nums:
if nums[k] != num:
nums[k + 1] = num
k += 1
return k + 1
Notice that we return k + 1
to match the custom judge’s assert condition.
The time complexity is O(n)
, because the for-loop iterates through the nums
array.
The space complexity is O(1)
, because the code operates in place, modifying the nums
array without using the additional data structure.
📌 Thoughts
I didn’t draw the data structure until now, but drawing the data structure helped me understand the algorithm.
If allowed, I will draw until I get comfortable with the data structure and algorithm. Also, this was quite easy to solve since the problem was very similar to the previous one.
💻 Solution
set()
approach / not in-place
def removeDuplicates(self, nums: List[int]) -> int:
nums[:] = set(nums)
return len(nums)
Two-pointer approach / in-place
def removeDuplicates(self, nums: List[int]) -> int:
k = 0
for num in nums:
if nums[k] != num:
nums[k + 1] = num
k += 1
return k + 1
Comments