代码随想录 - Day16 - 双指针法
151. 反转字符串中的单词
strip()
用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
str.strip([chars])
- chars – 移除字符串头尾指定的字符序列
- 返回移除字符串头尾指定的字符生成的新字符串
法1
# 删除前后空白
s = s.strip()
# 反转整个字符串
s = s[::-1]
# 将字符串拆分为单词,并反转每个单词
s = ' '.join(word[::-1] for word in s.split())
return s
法2
# 将字符串拆分为单词,即转换成列表类型
words = s.split()
# 反转单词
left, right = 0, len(words) - 1
while left < right:
words[left], words[right] = words[right], words[left]
left += 1
right -= 1
# 将列表转换成字符串
return " ".join(words)
206. 反转链表
画图理解能好想一点
prev, curr = None, head
# T O(n) M O(1)
while curr:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
return prev
19. 删除链表的倒数第 N 个结点
本来想试试不用虚拟头结点,但最终发现如果不用虚拟头结点,就无法处理head = [1], n = 1
的情况
# 创建一个虚拟节点,并将其下一个指针设置为链表的头部
dummy_head = ListNode(0, head)
slow = dummy_head
quick = dummy_head
while n >= 0:
quick = quick.next
n -= 1
while quick:
quick = quick.next
slow = slow.next
slow.next = slow.next.next
return dummy_head.next
面试题 02.07. 链表相交
curA, curB = headA, headB
cntA, cntB = 0, 0
# 计算两个链表的长度
while curA:
curA = curA.next
cntA += 1
while curB:
curB = curB.next
cntB += 1
# 计算长度差
step = abs(cntA - cntB)
# 更新两节点位置
curA, curB = headA, headB
if cntA > cntB:
while step > 0:
curA = curA.next
step -= 1
elif cntA < cntB:
while step > 0:
curB = curB.next
step -= 1
# 比较节点
while curA:
if curA == curB: # 若相等则返回
return curA
# 前进
curA = curA.next
curB = curB.next
# 没有相交的点,返回None
return None
142. 环形链表 II
slow, fast = head, head
while fast != None and fast.next != None:
slow = slow.next # 慢指针一次走一个
fast = fast.next.next # 快指针一次走两个
if slow == fast: # 若相等则成环
i1 = fast # 找环的入口
i2 = head
while i1 != i2:
i1 = i1.next
i2 = i2.next
return i2
return None
15. 三数之和
nums.sort() # 给序列排序
res = []
for position in range(len(nums)):
if nums[position] > 0: # 排除特殊情况
break
# 去重
if position > 0 and nums[position] == nums[position - 1]:
continue
left = position + 1
right = len(nums) - 1
while right > left:
if nums[position] + nums[left] + nums[right] > 0:
right -= 1
elif nums[position] + nums[left] + nums[right] < 0:
left += 1
else:
res.append([nums[position], nums[left], nums[right]])
# 去重
while right > left and nums[right] == nums[right - 1]:
right -= 1
while right > left and nums[left] == nums[left + 1]:
left += 1
right -= 1
left += 1
return res
18. 四数之和
三数之和是以0
为标准,四数之和要考虑到target
不确定,所以判断条件要改,要注意target
。
res = []
nums.sort()
for k in range(len(nums)):
# 剪枝处理
if nums[k] > target and nums[k] >= 0:
break
# 对nums去重
if k > 0 and nums[k] == nums[k - 1]:
continue
for i in range(k + 1, len(nums)):
# 剪枝处理
if nums[k] > target and nums[k] >= 0:
break
# 对nums[i]去重
if i > k + 1 and nums[i] == nums[i - 1]:
continue
left = i + 1
right = len(nums) - 1
while right > left:
if nums[k] + nums[i] + nums[left] + nums[right] > target:
right -= 1
elif nums[k] + nums[i] + nums[left] + nums[right] < target:
left += 1
else:
res.append([nums[k], nums[i], nums[left], nums[right]])
# 对nums[left]和nums[right]去重
while right > left and nums[right] == nums[right - 1]:
right -= 1
while right > left and nums[left] == nums[left + 1]:
left += 1
right -= 1
left += 1
return res
双指针应用
- 移除数组元素
- 字符传替换、填充、删除
- 链表涉及查找/删除特定元素的问题
- N数之和问题