本文主要是记录一下自己写过的双指针题目,基本是力扣hot100题里的,持续更新
双指针,指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。换言之,双指针法充分使用了数组有序这一特征,从而在某些情况下能够简化一些运算。
对撞指针是指在有序数组中,将指向最左侧的索引定义为左指针(left)
,最右侧的定义为右指针(right)
,然后从两头向中间进行数组遍历。
对撞数组适用于有序数组,也就是说当你遇到题目给定有序数组时,应该第一时间想到用对撞指针解题。
反转字符串https://leetcode-cn.com/problems/reverse-string/
此题的要求为,原地修改数组,第一反应就是利用双指针求解
左指针为第一个字符,右指针为最后一个字符,交换左右指针后左指针向右走一步,右指针向左走一步,如此反复直到左右指针相撞为止。
python代码如下:
class Solution:
def reverseString(self, s: List[str]) -> None:
left = 0
right = len(s) - 1
while left <= right:
s[left],s[right] = s[right],s[left]
left += 1
right -= 1
return s
有序数组的平方https://leetcode-cn.com/problems/squares-of-a-sorted-array/
由于是要生成这个数组的平方数组,而且数组是从小到大排序,有三种可能情况(举例子说明),第一种:全负数,比如[-5,-4,-3,-2,-1]
第二种:全正数,比如[1,2,3,4,5]
第三种:有正有负,比如[-4,-3,0,1,2],[-2,-1,0,1,99]
不管是哪种情况,我们可以确定最大值要么在最左侧,要么在最右侧。
直接分配两个指针,left = 0,right = len(nums)- 1,再安排一个list用于存储生成的平方数,site则为list的位置,从右到左安排。如果nums[right]的平方要大于nums[left]的平方,那么把这一数值存入list的site位中,如果nums[right]的平方要小于等于nums[left]的平方,那么存的就是nums[left]的平方了。当左右指针相撞时(也就是循环条件为while left <= right),平方数也存完了。
python代码如下:
class Solution(object):
def sortedSquares(self, nums):
left = 0
right = len(nums) - 1
pf_nums = [0] * len(nums) #建立一个数组存储平方数
pf_site = len(nums) - 1 #记录存储平方数的位置,从右向左移动
while right >= left:
if nums[right] * nums[right] > nums[left] * nums[left]: #哪个大存哪个
pf_nums[pf_site] = nums[right] * nums[right] #将较大值存入相应的平方数组位置
right -= 1 #右指针向左移动
elif nums[right] * nums[right] <= nums[left] * nums[left]:
pf_nums[pf_site] = nums[left] * nums[left]
left += 1 #左指针向右移动
pf_site -= 1 #每存一个数字,存储的位置就向左移动一次
return pf_nums
两数之和 II - 输入有序数组https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/
根据题目可知,此序列为递增序列,那么左边的肯定最小,右边的肯定最大,左指针为0 右指针为len-1,如果两个之和比目标值要小,那么就要增大最小值,也就是左指针右移,如果两个之和比目标值要大,那么减小最大值,也就是右指针左移。
python代码如下:
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
left = 0
right = len(numbers) - 1
while left < right:#不能返回两个相同数字因此是left小于right
if numbers[left] + numbers[right] == target:
return left+1 ,right+1
elif numbers[left] + numbers[right] < target:
left += 1
elif numbers[left] + numbers[right] > target:
right -= 1
反转字符串中的单词 IIIhttps://leetcode-cn.com/problems/reverse-words-in-a-string-iii/
首先对句子进行切片处理,分解为一个个单词,对每个单词进行处理,每个单词的第一个字母为左指针,最后一个字母为右指针,左右指针交换位置即可,再通过join函数组合起来即可
class Solution:
def reverseWords(self, s: str) -> str:
words = s.split() #首先分解句子变为一个个单词
s_r = []
for str in words:
str = list(str)
left = 0
right = len(str) - 1
while left < right:
str[left],str[right] = str[right],str[left]
left += 1
right -= 1
s_r.append(''.join(str))
return ' '.join(s_r)
快慢指针就是定义两根指针,一般为slow和fast,移动的速度一快一慢,以此来制造出自己想要的差值。
力扣283.移动零
移动零https://leetcode-cn.com/problems/move-zeroes/
此题不是经典的快慢指针,经典的快慢指针是快指针走两步慢指针走一步
此题让快指针为遍历指针,慢指针在原地待命,快指针遍历nums里的所有元素,遇到不为0的则让慢指针位置的值变为快指针位置的值,同时慢指针向右移动一步,快指针遍历完之后,再将后面的元素(慢指针所在位置开始)全部变为0
python代码如下:
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
fast = 0 #遍历指针
slow = 0 #为非0了再进1
while fast <= len(nums) - 1:
if nums[fast] != 0:
nums[slow] = nums[fast]
slow += 1
fast += 1
nums[slow:] = list(0 for i in range(len(nums)-slow))
return nums