链表题目及逻辑
1. BM1 反转链表
下面第一个代码,尽管是对的,但对于下面的题型来说,第二种逻辑是最合适的;其中cur指向cur.next.next;这里要求cur.next不为空。
class Solution:
def ReverseList(self , head: ListNode) -> ListNode:
# write code here
cur = ListNode(-1)
while head:
tmp = head.next
head.next = cur.next
cur.next = head
head = tmp
return cur.next
class Solution:
def ReverseList(self , head: ListNode) -> ListNode:
# write code here
if not head:
return head
cur = ListNode(-1)
cur.next = head
while head.next:
tmp = head.next
head.next = tmp.next
tmp.next = cur.next
cur.next = tmp
return cur.next
2. BM2 链表内指定区间反转
class Solution:
def reverseBetween(self , head: ListNode, m: int, n: int) -> ListNode:
# write code here
res = ListNode(-1) # 头节点
res.next = head
pre = res # 第m-1个节点
cur = res.next # 第m个节点
for i in range(m-1):
pre = pre.next
cur = cur.next
# cur和pre不动
for i in range(m, n):
tmp = cur.next
cur.next = tmp.next
tmp.next = pre.next
pre.next = tmp
return res.next
3. BM3 链表中的节点每k个一组翻转
class Solution:
def reverseKGroup(self , head: ListNode, k: int) -> ListNode:
# write code here
# 初始化结点
res = ListNode(-1)
res.next = head
# 统计链表节点数
num = 0
while head:
head = head.next
num += 1
cur = res
head = res.next
for i in range(num//k):
for j in range(k-1):
tmp = head.next
head.next = tmp.next
tmp.next = cur.next
cur.next = tmp
cur = head
head = head.next
return res.next
4. BM4 合并两个排序的链表
class Solution:
def Merge(self , pHead1: ListNode, pHead2: ListNode) -> ListNode:
# write code here
res = ListNode(-1)
cur = res
while pHead1 and pHead2:
if pHead1.val >= pHead2.val:
cur.next = pHead2
pHead2 = pHead2.next
else:
cur.next = pHead1
pHead1 = pHead1.next
cur = cur.next
cur.next = pHead1 if pHead1 else pHead2
return res.next
5. BM5 合并k个已排序的链表
通过递归的方法将k个已排序链表转化为两个已排序链表
import sys
# 甚至递归深度
sys.setrecursionlimit(100000)
class Solution:
def mergeKLists(self , lists: List[ListNode]) -> ListNode:
# write code here
if len(lists)==0:
return None
return self.divideMerge(lists, 0, len(lists)-1)
def divideMerge(self, lists, left, right):
# 二分递归
if right <= left:
return lists[left]
mid = (right - left)//2 + left
return self.merge2(self.divideMerge(lists, left, mid), self.divideMerge(lists, mid +1, right))
def merge2(self, pHead1, pHead2):
# 合并两个升序链表
if not pHead1:
return pHead2
if not pHead2:
return pHead1
res = ListNode(-1)
cur = res
while pHead1 and pHead2:
if pHead1.val >= pHead2.val:
cur.next = pHead2
pHead2 = pHead2.next
else:
cur.next = pHead1
pHead1 = pHead1.next
cur = cur.next
cur.next = pHead1 if pHead1 else pHead2
return res.next
6. BM6 判断链表中是否有环
双指针的运用
class Solution:
def hasCycle(self , head: ListNode) -> bool:
slow, fast = head, head
while(fast):
if fast.next and fast.next.next:
fast = fast.next.next
slow = slow.next
else:
break
if slow == fast:
return True
return False
7. BM7 链表中环的入口结点
我的逻辑就是只要记住这题能推理就行
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
slow, fast = pHead, pHead
while fast:
if fast.next and fast.next.next:
fast = fast.next.next
slow = slow.next
else:
return None
if slow == fast:
break
slow = pHead
while slow:
if slow == fast:
return slow
slow = slow.next
fast = fast.next
return None
8. BM8 链表中倒数最后k个结点
双指针
class Solution:
def FindKthToTail(self , pHead: ListNode, k: int) -> ListNode:
# write code here
if not pHead:
return None
cur = pHead
length = 0
while cur:
cur = cur.next
length += 1
if length < k:
return None
slow, fast = pHead, pHead
for i in range(k):
fast = fast.next
while(fast):
fast = fast.next
slow = slow.next
return slow
9. BM9 删除链表的倒数第n个节点
逻辑上,倒数第k个节点和倒数第n个节点没啥差别,但一个是第k,另一个是k+1的逻辑
class Solution:
def removeNthFromEnd(self , head: ListNode, n: int) -> ListNode:
# write code here
res = ListNode(-1)
res.next = head
slow, fast = res, res
while n:
if fast and fast.next:
fast = fast.next
else:
return None
n -= 1
while fast.next:
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return res.next
10. BM10 两个链表的第一个公共结点
考虑一下,有公共节点就是公共节点,没有就是空,每个节点走完一遍链表
class Solution:
def FindFirstCommonNode(self , pHead1 , pHead2 ):
# write code here
cur1, cur2 = pHead1, pHead2
while cur1 != cur2:
cur1 = pHead2 if not cur1 else cur1.next
cur2 = pHead1 if not cur2 else cur2.next
return cur1
11. BM11 链表相加(二)
class Solution:
def addInList(self , head1: ListNode, head2: ListNode) -> ListNode:
# write code here
# 栈
if not head1:
return head2
if not head2:
return head1
s1 = []
s2 = []
while head1:
s1.append(head1)
head1 = head1.next
while head2:
s2.append(head2)
head2 = head2.next
res = ListNode(-1)
num = 0
while(len(s1) and len(s2)):
num1 = s1.pop().val
num2 = s2.pop().val
num = num + num1 + num2
t = ListNode(num%10)
t.next = res.next
res.next = t
num = num//10
while(len(s1)):
num1 = s1.pop().val
num = num + num1
t = ListNode(num%10)
t.next = res.next
res.next = t
num = num//10
while(len(s2)):
num2 = s2.pop().val
num = num + num2
t = ListNode(num%10)
t.next = res.next
res.next = t
num = num//10
if num > 0:
t = ListNode(num)
t.next = res.next
res.next = t
return res.next
12. BM12 单链表的排序
class Solution:
def sortInList(self , head: ListNode) -> ListNode:
# write code here
# 递归终止条件
if(not head or not head.next):
return head
# 归并排序中点
fast = head.next
slow = head
while (fast and fast.next):
slow = slow.next
fast = fast.next.next
# 从中间截断链表
tmp = slow.next
slow.next = None
left = self.sortInList(head)
right = self.sortInList(tmp)
# 链表合并
res = ListNode(-1)
cur = res
while left and right:
if left.val > right.val:
cur.next = right
right = right.next
else:
cur.next = left
left = left.next
cur = cur.next
# 处理尾链
cur.next = left if left else right
return res.next
13. BM13 判断一个链表是否为回文结构
class Solution:
def isPail(self , head: ListNode) -> bool:
# write code here
if not head or not head.next:
return True
# 快慢指针找链表中点
slow = head
fast = head.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
tmp = slow
# 逆序后半部分链表
cur = tmp.next
tmp.next = None
while cur:
t = cur.next
cur.next = tmp.next
tmp.next = cur
cur = t
tmp = tmp.next
while(tmp and head):
print(tmp.val, head.val)
if (tmp.val != head.val):
return False
tmp = tmp.next
head = head.next
return True
14. BM14 链表的奇偶重排
class Solution:
def oddEvenList(self , head: ListNode) -> ListNode:
# write code here
if not head or not head.next:
return head
h1 = ListNode(-1)
cur = head
p1 = ListNode(-1)
p2 = h1
while cur:
p1.next = cur
p1 = p1.next
cur = cur.next
if not cur:
p2.next = None
break
p2.next = cur
p2 = p2.next
cur = cur.next
p1.next = h1.next
return head
15. BM15 删除有序链表中重复的元素-I
class Solution:
def deleteDuplicates(self , head: ListNode) -> ListNode:
# write code here
if not head or not head.next:
return head
res = ListNode(-1)
res.next = head
while head and head.next:
while head.next and head.val == head.next.val:
head.next = head.next.next
head = head.next
return res.next
16. BM16 删除有序链表中重复的元素-II
class Solution:
def deleteDuplicates(self , head: ListNode) -> ListNode:
# write code here
if not head or not head.next:
return head
res = ListNode(-1)
pre = res
flag = False
while head:
while head.next and head.val == head.next.val:
head.next = head.next.next
flag = True
if not flag:
pre.next = head
pre = pre.next
head = head.next
pre.next = None
else:
head = head.next
flag = False
return res.next