一、算法讲解
主要用于遍历数组,两个指针指向不同元素,也可以延伸到多个数组的多个指针。
若两个指针指向同一数组,遍历方向相同且不会相交,则也称为滑动窗口(两个指针包围的区域即为当前的窗口),经常用于区间搜索。
若两个指针指向同一数组,但是遍历方向相反,则可以用来进行搜索,待搜索的数组往往是排好序的。
二、题型
2.1 两数之和
给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
指定两个指针,左指针指向数组的开头,右指针指向数组的尾部,每次比较两个指针的和和target的大小。如果两指针之和大于target,那么右指针往左边移动(变小)。如果两指针之和小于target,那么左指针往右边移动(变大)。
2.2 归并两个有序数组
题目介绍:
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。
nums1, nums2有序,这道题可以设定两个指针,分别指向nums1, nums2。为了操作方便,可以将指针指向nums1, nums2的末尾。比较大小并执行插入操作。
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
# 从后面往前面做反而容易
if len(nums1) == len(nums2):
nums1[:n] = nums2[:n]
p1 = m - 1
p2 = n - 1
end = m + n - 1
while p1 >= 0 and p2 >= 0:
if nums1[p1] > nums2[p2]:
nums1[end] = nums1[p1]
p1 -= 1
end -= 1
else:
nums1[end] = nums2[p2]
p2 -= 1
end -= 1
if p1 < 0:
nums1[:end + 1] = nums2[:p2 + 1]
3.4 快慢指针
题目描述:
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
对于环形链表,有一个通用的解法,快慢指针。给定两个指针,
分别命名为 slow 和 fast,起始位置在链表的开头。每次 fast 前进两步,slow 前进一步。如果 fast
可以走到尽头,那么说明没有环路;如果 fast 可以无限走下去,那么说明一定有环路,且一定存在一个时刻 slow 和 fast 相遇。当 slow 和 fast 第一次相遇时,我们将 fast 重新移动到链表开头,并让 slow 和 fast 每次都前进一步。当 slow 和 fast 第二次相遇时,相遇的节点即为环路的开始点。
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
if not head or not head.next: return
slow = head
fast = head
while fast.next:
slow = slow.next
fast = fast.next
if fast.next:
fast = fast.next
else:
return
if fast == slow:
fast = head
while fast != slow:
slow = slow.next
fast = fast.next
return fast
return
# 最后的return表示没有环形的一种情况,比如[3,5,6],虽然不写也正确,但是写上更完整