双指针 Two Pointer
双指针分为两种:对撞指针 & 快慢指针
常用数组中
对撞指针
LeetCode 167题目
经典题目: Two sum
方法一:暴力解法
时间复杂度:O(n^2)
缺点:没有应用数组本身特点性质
方法二:数组有序,二分搜索法
时间复杂度:O(nlogn)
二分搜索时间复杂度是O(logn)
i 从0-n遍历 O(n)
j 从i-n遍历用 二分搜索法 O(logn)
方法三:双指针法
数组nums有序的
左指针 i 右指针 j
判断nums[i] + nums[j] == target
如果小于,则 i + 1 ,i右移再判断
如果大于,则 j + 1, j左移再判断
直到 i 跟 j 相撞
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
# 时间复杂度O(n)
# 空间复杂的O(1)
i , j = 0, len(numbers)-1
while i < j :
if numbers[i] + numbers[j] == target:
break
elif numbers[i] + numbers[j] < target:
i += 1;
elif numbers[i] + numbers[j] > target:
j -= 1;
return [i+1, j+1]
对撞指针的应用
快慢指针
LeetCode 142题目
Set集合,增加条件空间复杂度为1,怎该方法不能使用
定义
步骤:
- 定义fast指针和slow指针,fast一次二步,slow一次一步
- 第一步fast->2, slow->3, fast->1,slow->2, fast->8, slow->7,fast->4,slow->1, fast->6,slow->6相遇!!!
- 定义一个指针p从最开始按照一次一步移动,和slow的频率一样,p和slow相遇的节点就是环的入口点。
证明:
- a = 从开始位置到入环口步数
- b = 一环的步数
- fast = 2 * slow
- fast = slow + nb
- slow = nb
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
fast, slow = head, head
while fast != None:
fast = fast.next
if fast == None:
break
fast = fast.next
# fast 两步
slow = slow.next
# slow 一步
if slow == fast:
break
if fast == None:
return None
p1, p2 = slow, head
while p1 != p2:
p1 = p1.next
p2 = p2.next
return p1