leetcode-双指针
1、移除元素(用的不是双指针)
2、反转字符串(用的不是双指针)
class Solution:
def reverseString(self, s: List[str]) -> None:
s[:] = s[::-1]
return s
3、替换空格(用的不是双指针)
4、翻转字符串里的单词(用的不是双指针)
class Solution:
def reverseWords(self, s: str) -> str:
return ' '.join(s.split()[::-1])
5、反转链表(更新pre、cur指针需注意顺序)
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
pre = None
cur = head
while cur :
tmp = cur.next ## 保存一下 cur的下一个节点,因为接下来要改变cur->next
cur.next = pre #反转
#更新pre、cur指针
pre = cur
cur = tmp
return pre
6、删除链表的倒数第N个节点(return dummy.next)
19 删除链表的倒数第N个节点
1 、初始时first 和second 均指向头节点。我们首先使用first 对链表进行遍历,遍历的次数为 n。此时,first 和second 之间间隔了 n-1 个节点,即first 比second 超前了 n 个节点。
在这之后,我们同时使用first 和second 对链表进行遍历。当first 遍历到链表的末尾(即first 为空指针)时,second 恰好指向倒数第 n个节点。
2、在对链表进行操作时,一种常用的技巧是添加一个哑节点(dummy node),它的next 指针指向链表的头节点。这样一来,我们就不需要对头节点进行特殊的判断了。
⚠️return dummy.next 而非second
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
dummy = ListNode(0, head)
first = head
second = dummy
for i in range(n):
first = first.next
while first:
first = first.next
second = second.next
second.next = second.next.next
return dummy.next
7、链表相交
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
if not headA or not headB:
return None
a = headA
b = headB
while a != b:
a = a.next if a else headB
b = b.next if b else headA
return a
8、环形链表
142 环形链表
分别定义 fast 和 slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# 如果相遇
if slow == fast:
p = head
q = slow
while p!=q:
p = p.next
q = q.next
#你也可以return q
return p
return None
9、三数之和(排序+双指针)
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
nums.sort()
ans = []
for i in range(n):
if nums[i] > 0: #第一个数就大于0,不存在
break
if i > 0 and nums[i] == nums[i-1]: #对第一个数去重
continue
left = i+1
right = n-1
while left < right:
total = nums[i] + nums[left] + nums[right]
if total > 0: right -= 1
elif total < 0 : left += 1
else:
ans.append([nums[i],nums[left], 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 ans
10、四数之和(排序+双指针)
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
n = len(nums)
nums.sort()
ans = []
for i in range(n):
if i > 0 and nums[i] == nums[i-1]: continue #对第一个数去重
for j in range(i+1,n):
if j > i+1 and nums[j] == nums[j-1]: continue #对第二个数去重
left = j+1
right = n-1
while left < right:
total = nums[i] + nums[j] + nums[left] + nums[right]
if total > target: right -= 1
elif total < target : left += 1
else:
ans.append([nums[i],nums[j],nums[left], 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 ans
11、盛最多水的容器(双指针)
class Solution:
def maxArea(self, height: List[int]) -> int:
l,r = 0,len(height)-1
max_area = 0
while l <=r:
max_area = max(max_area, (r-l)*min(height[l],height[r]))
#移动矮的
if height[l] <= height[r]:
l += 1
else:
r -= 1
return max_area
12、16. 最接近的三数之和
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
n = len(nums)
best = 10**7
def update(cur):
nonlocal best
if abs(cur-target) < abs(best-target):
best = cur
for i in range(n):
if i > 0 and nums[i] == nums[i-1]: #第一个数去重
continue
left = i+1
right = n-1
while left < right:
total = nums[i] + nums[left] + nums[right]
if total == target:
return total
update(total)
if total > target:
r = right - 1 #右指针左移
#去重
while left < r and nums[r] == nums[right]:
r -= 1
right = r
else:
l = left + 1 #左指针右移
#去重
while l < right and nums[l] == nums[left]:
l += 1
left = l
return best