Leetcode--移除元素(27)
题目描述:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
(1)思路一: 直接使用python中的remove函数,移除列表中某个值的第一个匹配项。
1 class Solution: 2 def removeElement(self, nums: List[int], val: int) -> int: 3 while val in nums: 4 nums.remove(val) 5 return len(nums)
时间复杂度:O(n)
(2)思路二:类似删除重复项(26),使用双指针。同样是一个快指针和一个慢指针,慢指针用来记录最终的nums,快指针用来遍历列表中的所有元素。
1 class Solution: 2 def removeElement(self, nums: List[int], val: int) -> int: 3 length =len(nums) 4 i = 0 5 j = 0 6 while j < length: 7 if nums[j] != val: 8 nums[i] = nums[j] 9 i += 1 10 j += 1 11 return i
时间复杂度O(n),假设数组共有n个元素,i和j至少遍历2n步 空间复杂度O(1) 时间及内存消耗:
优化:
当列表中需要删除的元素出现次数很少时,例如[4,1,2,3,5]要移除4时,如果采用上述双指针法则需要依次对前四个元素进行左移操作。而由于题目中提到,元素的顺序可以改变。因此在这种情况下,其实只需要将4和列表中的最后一个元素交换位置即可。因此有一种更为优雅的双指针方法:两个指针i和j分别指向头和尾,当i所指向的值等于所需要删除的值时,则将i与j所指向的元素互换,同时j-1;否则直接i+1即可。
1 class Solution: 2 def removeElement(self, nums: List[int], val: int) -> int: 3 i = 0 4 j = len(nums) 5 while i < j: 6 if nums[i] == val: 7 nums[i] = nums[j-1] 8 j -= 1 9 else: 10 i += 1 11 return j
时间复杂度:O(n),在此种方法中,i和j相遇最多需要遍历n步,因此更加高效。