image.png

一、双指针技巧总结

image.png

1、快慢指针

image.png

1、判定链表中是否含有环

141.环形链表https://leetcode-cn.com/problems/linked-list-cycle/
image.png
image.pngimage.png

  1. class Solution:
  2. def hasCycle(self, head: ListNode) -> bool:
  3. slow, fast = head, head
  4. while fast!=None and fast.next!=None:
  5. slow = slow.next
  6. fast=fast.next.next
  7. if slow == fast:
  8. return True
  9. return False

2、已知链表中含有环,返回这个环的起始位置

142.环形链表2https://leetcode-cn.com/problems/linked-list-cycle-ii/
image.pngimage.png

  1. class Solution(object):
  2. def detectCycle(self, head):
  3. fast, slow = head, head
  4. while fast and fast.next:
  5. fast, slow = fast.next.next, slow.next
  6. if fast == slow:
  7. break
  8. slow = head # 注意这一步
  9. while fast != slow:
  10. fast, slow = fast.next, slow.next
  11. return slow

image.pngimage.png

3、寻找链表的中点

image.png

  1. while fast and fast.next:
  2. fast, slow = fast.next.next, slow.next
  3. return slow

image.png
image.png

4、寻找链表的倒数第 k 个元素

image.png

√·5、26、删除有序数组中的重复项

滑动窗⼝算法框架 - 图15

  1. class Solution:
  2. def removeDuplicates(self, nums: List[int]) -> int:
  3. i,j=0,0
  4. if len(nums)<2: return len(nums)
  5. for i in range(1,len(nums)): # 注意 (1,N)
  6. if nums[i]!=nums[i-1]: # 注意
  7. j+=1
  8. nums[j]=nums[i]
  9. return j+1

√·6、27. 移除元素

image.png

  1. class Solution:
  2. def removeElement(self, nums: List[int], val: int) -> int:
  3. j=0
  4. for i in range(len(nums)):
  5. if nums[i]!=val:
  6. nums[j]=nums[i]
  7. j+=1
  8. return j

2、左右指针

image.png

1、⼆分查找

image.png
image.png

2、两数之和

image.pngimage.png
image.png

3、反转数组

image.png

3、不知道什么指针

1、剑指 Offer 24. 反转链表

  1. # Definition for singly-linked list.
  2. # class ListNode:
  3. # def __init__(self, x):
  4. # self.val = x
  5. # self.next = None
  6. class Solution:
  7. def reverseList(self, head: ListNode) -> ListNode:
  8. pre, cur = None, head
  9. while cur:
  10. nxt = cur.next
  11. cur.next = pre
  12. pre = cur
  13. cur = nxt
  14. return pre

2、剑指 Offer 25. 合并两个排序的链表

  1. # Definition for singly-linked list.
  2. # class ListNode:
  3. # def __init__(self, x):
  4. # self.val = x
  5. # self.next = None
  6. class Solution:
  7. def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
  8. cur = dum = ListNode(0) # 伪头结点!绝了
  9. while l1 and l2:
  10. if l1.val < l2.val:
  11. cur.next, l1 = l1, l1.next
  12. else:
  13. cur.next, l2 = l2, l2.next
  14. cur = cur.next
  15. cur.next = l1 if l1 else l2
  16. return dum.next

√·3、88. 合并两个有序数组(逆序指针)

  1. class Solution:
  2. def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
  3. """
  4. Do not return anything, modify nums1 in-place instead.
  5. """
  6. n1=m
  7. n2=n
  8. res=m+n-1
  9. while n1 and n2:
  10. if nums1[n1-1]<nums2[n2-1]:
  11. nums1[res]=nums2[n2-1]
  12. n2-=1
  13. else:
  14. nums1[res]=nums1[n1-1]
  15. n1-=1
  16. res-=1
  17. if n2>0: nums1[:n2]=nums2[:n2]

√4、28. 实现 strStr()

image.png

  1. class Solution:
  2. def strStr(self, haystack: str, needle: str) -> int:
  3. i,j=0,0
  4. n=len(needle)
  5. if n==0 :
  6. return 0
  7. while i<len(haystack):
  8. if haystack[i]==needle[j]:
  9. j+=1
  10. n-=1
  11. i+=1 # 注意
  12. else:
  13. i=i-j+1 # 注意
  14. j=0
  15. n=len(needle)
  16. if n==0:
  17. return i-len(needle)
  18. return -1

二、滑动窗口

image.pngimage.pngimage.pngimage.png

1、最小覆盖子串

image.pngimage.pngimage.pngimage.pngimage.pngimage.pngimage.png

2、字符串排列

image.pngimage.pngimage.png

3、找所有字母异位词

image.pngimage.png
画圈的那个部分,可以保证不包含其他的字符串。
当right-left==t.size 时, 不符合条件,说明含有其他的字符串,这个时候会对左边界进行更新。
但是怎么排除结果和字符是字母一样,顺序不一样呢

4、最长无重复子串

image.pngimage.png
滑动窗⼝算法框架 - 图43
滑动窗⼝算法框架 - 图44

×5、220. 存在重复元素 III

  1. # class Solution:
  2. # def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
  3. # for i in range(len(nums)):
  4. # for j in range(1,k+1):
  5. # if i+j<len(nums) and abs(nums[i]-nums[i+j])<=t:
  6. # return True
  7. # return False
  8. class Solution(object):
  9. def containsNearbyAlmostDuplicate(self, nums, k, t):
  10. from sortedcontainers import SortedSet
  11. st = SortedSet()
  12. left, right = 0, 0
  13. res = 0
  14. while right < len(nums):
  15. if right - left > k: # 移动窗口
  16. st.remove(nums[left])
  17. left += 1
  18. # 在st中查找nums[right] - t,存在时返回nums[right] - t左侧的位置,不存在返回应该插入的位置.
  19. index = bisect.bisect_left(st, nums[right] - t)
  20. if st and index >= 0 and index < len(st) and abs(st[index] - nums[right]) <= t:
  21. return True
  22. st.add(nums[right])
  23. right += 1
  24. return False