1. 指针移动速度不同(快慢指针)

​141. 环形链表​​(判断是否有环)

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def hasCycle(self, head: ListNode) -> bool:
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast: return True
return False

​26. 删除有序数组中的重复项​

class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
slow = 0; fast = 1
while fast < len(nums):
if nums[slow] != nums[fast]:
slow += 1
nums[slow] = nums[fast]
fast += 1
return slow + 1

​876. 链表的中间结点​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def middleNode(self, head: ListNode) -> ListNode:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow

​202. 快乐数​

class Solution:
def getNext(self, n: int) -> int:
res = 0
while n > 0:
n, d = divmod(n, 10)
res += d ** 2
return res

def isHappy(self, n: int) -> bool:
slow = n; fast = self.getNext(n)
while fast != 1 and slow != fast:
slow = self.getNext(slow)
fast = self.getNext(self.getNext(fast))
return fast == 1
class Solution:
def isHappy(self, n: int) -> bool:
def sqrtsum(n: int) -> int:
return sum(map(lambda x: x ** 2,map(int,list(str(n)))))
if 1 < n < 10 and n != 7: return False
m = sqrtsum(n)
if m == 1: return True
else: return self.isHappy(m)

2. 指针位置不同

2.1 左右指针

2.1.1 回文:

​5. 最长回文子串​

class Solution:
def palindrome(self, s: str, left: int, right: int) -> str:
while(left>=0 and right<len(s) and s[left]==s[right]):
left-=1
right+=1
return s[left+1:right]

def longestPalindrome(self, s: str) -> str:
res=""
for i in range(len(s)):
#奇数回文子串
s1 = self.palindrome(s,i,i)
#偶数回文子串
s2 = self.palindrome(s,i,i+1)
res = res if len(res)>len(s1) else s1
res = res if len(res)>len(s2) else s2
return res

 ​​234. 回文链表​

​面试题 02.06. 回文链表​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
vals = []
cur = head
while cur:
vals.append(cur.val)
cur = cur.next
return vals == vals[::-1]

eg. ​​409. 最长回文串​

class Solution:
def longestPalindrome(self, s: str) -> int:
res = 0
flag = 0
c = Counter(s)
for v in c.values():
if v % 2 == 1: flag = 1
res += v//2*2
return res if flag == 0 else res + 1

 ​​剑指 Offer II 018. 有效的回文​

class Solution:
def isPalindrome(self, s: str) -> bool:
s = re.sub(r'[^A-Za-z0-9]','',s).lower()
return s==s[::-1]

​剑指 Offer II 019. 最多删除一个字符得到回文​

class Solution:
def isPalindrome(self, s: str) -> bool:
return s == s[::-1]

def validPalindrome(self, s: str) -> bool:
l = 0; r = len(s) - 1
while l <= r:
# 删除 s[l] 或 s[r], 判断
if s[l] != s[r]:
return self.isPalindrome(s[l:r]) or self.isPalindrome(s[l+1:r+1])
l += 1
r -= 1
return True

​647. 回文子串​

​剑指 Offer II 020. 回文子字符串的个数​

class Solution:
def countSubstrings(self, s: str) -> int:
res = 0
n = len(s)
for k in range(2*n-1):
l = k // 2
r = k // 2 + k % 2
while l >= 0 and r < n and s[l] == s[r]:
res += 1
l -= 1
r += 1
return res

2.1.2 nSum:

2Sum

class Solution:
def twoSum(self, nums: List[int], target: int) -> List[List[int]]:
left = 0; right = len(nums)-1
res = []
nums.sort()
while left < right:
sums = nums[left] + nums[right]
if sums < target:
left += 1
elif sums > target:
right -= 1
else:
res.append([left, right])
# 跳过所有重复元素
while left < right and nums[left] == nums[left+1]: left += 1
while left < right and nums[right] == nums[right-1]: right -= 1
left += 1; right -= 1
return res

3Sum:

class Solution:
def threeSum(self, nums: List[int], target: int) -> List[List[int]]:
res = [];
nums.sort()
for i in range(len(nums)):
left = i + 1; right = len(nums) - 1
if i > 0 and nums[i] == nums[i-1]: continue
while left < right:
sums = nums[i] + nums[left] + nums[right]
if sums < target: left += 1
elif sums > target: right -= 1
else:
res.append([nums[left],nums[i],nums[right]])
while left < right and nums[left] == nums[left+1]: left += 1
while left < right and nums[right] == nums[right-1]: right -= 1
left += 1; right -= 1
return res

eg.

​面试题 16.24. 数对和​

class Solution:
def pairSums(self, nums: List[int], target: int) -> List[List[int]]:
left = 0; right = len(nums)-1
res = []
nums.sort()
while left < right:
sums = nums[left] + nums[right]
if sums == target:
res.append([nums[left], nums[right]])
left += 1; right -= 1
elif sums < target:
left += 1
else:
right -= 1
return res

​剑指 Offer 57. 和为s的两个数字​

class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
lo = 0; hi = len(nums) - 1
while lo < hi:
sums = nums[lo] + nums[hi]
if sums == target: return [nums[lo], nums[hi]]
elif sums < target: lo += 1
elif sums > target: hi -= 1
return []

​剑指 Offer II 006. 排序数组中两个数字之和​

class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
l = 0; r = len(numbers) - 1
while l <= r:
sums = numbers[l] + numbers[r]
if sums == target: return [l,r]
elif sums < target: l += 1
elif sums > target: r -= 1

 ​​15. 三数之和​

class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
res = []; target = 0
nums.sort()
for i in range(len(nums)):
left = i + 1; right = len(nums) - 1
if i > 0 and nums[i] == nums[i-1]: continue
while left < right:
sums = nums[left] + nums[i] + nums[right]
if sums < target: left += 1
elif sums > target: right -= 1
else:
res.append([nums[left],nums[i],nums[right]])
while left < right and nums[left] == nums[left+1]: left += 1
while left < right and nums[right] == nums[right-1]: right -= 1
left += 1; right -= 1
return res
class Solution:
def twoSum(self, nums: List[int], start: int, target: int) -> List[List[int]]:
lo = start; hi = len(nums)-1
res = []
nums.sort()
while lo < hi:
left = nums[lo]; right = nums[hi]
sums = nums[lo] + nums[hi]
if sums < target:
lo += 1
elif sums > target:
hi -= 1
else:
res.append([nums[lo], nums[hi]])
while lo < hi and nums[lo] == left: lo += 1
while lo < hi and nums[hi] == right: hi -= 1
return res

def threeSum(self, nums: List[int]) -> List[List[int]]:
res = []
nums.sort()
for i in range(len(nums)):
twoSumTarget = 0 - nums[i]
twoSumRes = self.twoSum(nums, i+1, twoSumTarget)
for it in twoSumRes:
it.append(nums[i])
res.append(it)
ans = list(set(map(lambda x: tuple(sorted(x)), res)))
return ans

​16. 最接近的三数之和​

class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
res = nums[0] + nums[1] + nums[2]
nums.sort()
for i in range(len(nums)):
left = i + 1; right = len(nums) - 1
while left < right:
sums = nums[left] + nums[i] + nums[right]
res = sums if abs(sums - target) < abs(res - target) else res
if sums < target: left += 1
elif sums > target: right -= 1
else: return res
return res

2.1.3 example

​11. 盛最多水的容器​

class Solution:
def maxArea(self, height: List[int]) -> int:
res = 0
left = 0; right = len(height) - 1
while left < right:
# 相同条件下边界距离越远,面积越大,所以设置左右指针从两边向中间移动;哪个边界小,哪个边界移动重新寻找机会,希望用边界高度的增加弥补两边界距离的减小
if height[left] < height[right]:
res = max(res, (right - left) * height[left])
left += 1
else:
res = max(res, (right - left) * height[right])
right -= 1
return res

​剑指 Offer 21. 调整数组顺序使奇数位于偶数前面​

class Solution:
def exchange(self, nums: List[int]) -> List[int]:
l = 0; r = len(nums) - 1
while l <= r:
while l <= r and nums[l] % 2 == 1:
l += 1
while l <= r and nums[r] % 2 == 0:
r -= 1
if l > r: break
nums[l], nums[r] = nums[r], nums[l]
return nums

​75. 颜色分类​

class Solution:
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
if len(nums) < 2: return
# 循环不变量确定循环变量
# 0 in [0, p0), 1 in [p0, i), 2 in [p2, len(nums)]
i = 0; p0 = 0; p2 = len(nums) - 1
# 循环变量 i>p2 时, 跳出循环
while i <= p2:
if nums[i] == 0:
nums[i], nums[p0] = nums[p0], nums[i]
p0 += 1
i += 1
elif nums[i] == 1:
i += 1
else: # nums[i] == 2
nums[i], nums[p2] = nums[p2], nums[i]
# 由于不知道交换回来的nums[p2]的值,所以不对循环变量 i 操作,进入下一次循环判断
p2 -= 1

​面试题 02.04. 分割链表​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def partition(self, head: ListNode, x: int) -> ListNode:
# 不要用连等号
left, right = ListNode(0), ListNode(0)
sml, big = left, right
while head:
if head.val < x:
left.next = head
left = left.next
else:
right.next = head
right = right.next
head = head.next
left.next = big.next
right.next = None
return sml.next

​42. 接雨水​

​面试题 17.21. 直方图的水量​

class Solution:
def trap(self, height: List[int]) -> int:
# max min
res = 0
left = 0; right = len(height) - 1
# leftMax[i] 表示下标 i 及其左边的位置中,height 的最大高度,rightMax[i] 表示下标 i 及其右边的位置中,height 的最大高度。
leftmax = rightmax = 0
while left < right:
leftmax = max(leftmax, height[left])
rightmax = max(rightmax, height[right])
# 若 height[left] < height[right], 则 leftmax < rightmax
# 接的雨水由小边决定
if height[left] < height[right]:
res += leftmax - height[left]
left += 1
else:
res += rightmax - height[right]
right -= 1
return res

2.2  前后指针

​面试题 01.05. 一次编辑​

class Solution:
def oneEditAway(self, first: str, second: str) -> bool:
m = len(first); n = len(second)
if abs(m-n) > 1: return False
for i in range(min(m,n)):
if first[i] != second[i]:
return first[i+1:] == second[i+1:] or first[i+1:] == second[i:] or first[i:] == second[i+1:]
return True

​剑指 Offer 18. 删除链表的节点​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def deleteNode(self, head: ListNode, val: int) -> ListNode:
cur = head.next
pre = head
if head.val == val:
return head.next
while cur.val != val:
cur = cur.next
pre = pre.next
pre.next = cur.next
return head

​面试题 02.01. 移除重复节点​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
# hash table
def removeDuplicateNodes(self, head: ListNode) -> ListNode:
pre = None; cur = head
visited = set()
while cur:
if cur.val in visited:
# 删除cur
pre.next = cur.next
else:
visited.add(cur.val)
# pre指针后移到cur
pre = cur
cur = cur.next
return head

​剑指 Offer 22. 链表中倒数第k个节点​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
slow = fast = head
while k > 0:
fast = fast.next
k -= 1
while fast:
slow = slow.next
fast = fast.next
return slow

​面试题 02.02. 返回倒数第 k 个节点​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def kthToLast(self, head: ListNode, k: int) -> int:
slow = fast = head
while k > 0:
fast = fast.next
k -= 1
while fast:
slow = slow.next
fast = fast.next
return slow.val

​206. 反转链表​

​剑指 Offer II 024. 反转链表​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
pre, cur = None, head
while cur:
# 存储当前链表的下一个节点为临时变量
tmp = cur.next
# 当前链表的下一个指向前一个链表
cur.next = pre
# pre, cur整体往后移动一个位置
pre, cur = cur, tmp
return pre
def reverseList(self, head: ListNode) -> ListNode:
# 递归终止条件
if head is None or head.next is None:
return head

p = self.reverseList(head.next)
head.next.next = head
head.next = None

return p

​25. K 个一组翻转链表​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:

# 判断是否有k个节点
def cal_len(head):
p = head
cnt = 0
while p:
cnt += 1
p = p.next
if cnt >= k: return True
return False

# 翻转k个节点
def reverseK(head, k):
pre, cur = None, head
while k:
tmp = cur.next
cur.next = pre
pre, cur = cur, tmp
k -= 1
return pre, cur

# 递归
def dfs(head, k):
if not cal_len(head): return head
pre, cur = reverseK(head, k)
head.next = dfs(cur, k)
return pre

return dfs(head, k)

 ​​环形链表 II​

​剑指 Offer II 022. 链表中环的入口节点​

​面试题 02.08. 环路检测​

# 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:
slow, fast = head, head
while True:
if not fast or not fast.next: return None
slow = slow.next
fast = fast.next.next
if slow == fast: break
slow = head
while slow != fast:
fast = fast.next
slow = slow.next
return slow

 ​​160. 相交链表​

​剑指 Offer 52. 两个链表的第一个公共节点​

​剑指 Offer II 023. 两个链表的第一个重合节点​

​面试题 02.07. 链表相交​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
p = headA; q = headB
while p != q:
p = p.next if p else headB
q = q.next if q else headA
return p