双指针:
(1)27. 移除元素
题目描述:
给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
代码:
class Solution(object):
def removeElement(self, nums, val):
fast = 0
slow = 0
while fast < len(nums):
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
- 时间复杂度O(n)
- 空间复杂度O(1)
解释:
题目中重要的限制信息:不要使用额外的数组空间。暴力解法就需要双循环,第一次for旬循环找nums中数值不等于val的元素,第二次循环更新nums中的数值,时间复杂度是O(n^2),空间杂度O(1)。
考虑使用双指针。第一个指针(fast)不断寻找nums中数值不等于val的元素,第二个指针(slow)更新nums数组,当第一个指针到顶了以后,则nums前slow项已经全部更新完成,时间复杂度是O(n),空间复杂度O(1)。
步骤:
第一步:设置快慢指针
第二步:当fast指针到达列表最后一项时候停止更新fast指针
第三步:当fast指针所指元素不等于val时更新slow指针所指元素
第四步:当fast指针超过i列表最后一项时候返回slow的值,此时前slow项元素已经全部完成更新
(2)26. 删除有序数组中的重复项
题目描述:
给你一个有序数组 nums ,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
代码:
class Solution(object):
def removeDuplicates(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
slow = 0
fast = 1
while fast < len(nums):
if nums[fast]!= nums[slow]:
slow += 1
nums[slow] = nums[fast]
fast += 1
return slow+1
- 时间复杂度O(n)
- 空间复杂度O(1)
解释:
典型的双指针问题,有几个点需要注意:第一点是考虑数组长度为0的特殊情况,当长度为0时,数组不存在,也就没有办法通过后续的判断条件删除数组。第二点是当fast指针和slow指针所指的元素不同时,先将slow右移,再完成赋值。
(3)283. 移动零
题目描述:
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
代码:
class Solution(object):
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
slow = 0
fast = 0
while fast < len(nums):
if nums[fast] != 0:
nums[slow], nums[fast] = nums[fast], nums[slow] #交换
left += 1
fast += 1
return nums
- 时间复杂度O(n)
- 空间复杂度O(1)
解释:
典型双指针,需要注意的是交换的操作,nums[slow], nums[fast] = nums[fast], nums[slow]
,快指针指到非0元素的时候就和慢指针交换一下,这样就把所有的非0元素交换到了nums[ : slow+1]
,则剩余的0元素就集中在nums[slow+1 : -1]
(4)977. 有序数组的平方
题目描述:
给你一个按非递减顺序排序的整数数组 nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。
代码:
class Solution(object):
def sortedSquares(self, nums):
#两边大中间小,那么谁大把谁放进去就好了
n = len(nums)
i = 0
j = n-1
ins = n-1
ans = [0]*n
while j >= i:
if nums[j]*nums[j] >= nums[i]*nums[i]:
ans[ins] = nums[j]*nums[j]
j -= 1
ins -= 1
else:
ans[ins] = nums[i]*nums[i]
i += 1
ins -= 1
return ans
- 时间复杂度O(n)
- 空间复杂度O(1)
解释:
因为题目说明了非递减,那么数组两边元素的平方整体是比中间元素的平方大的,那么只需要双指针比较两端的平方大小,不断的压缩空间就可以啦。
总结
双指针的本质还是解决两个问题 1. 怎么建立快慢指针2. 快慢指针更新的条件,遇到双指针的题,从这两个问题入手,思路就会比较清晰。
写在最后,之前断断续续的刷过一些题,因为没有归纳整理,过一段时间后可能就忘记了,所以现在准备按照Carl大佬写的代码随想录重新系统的刷一遍leetcode,最后通过博客进行总结归纳,时常看看,如果有新的感悟也方便更新。