链表是由一堆 ListNode 构成的,每个 ListNode 记录了val 和 next 信息。如果是双链表的话,还会额外记录prev信息。因此,只要给出头结点(Head)的信息,就可以找到整个列表了。
链表相关题目
203. 移除链表元素
trick:单独处理头结点比较麻烦,因此增加虚拟头结点
dummy_head=ListNode(next=head)
尾结点 cur.next==None
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
dummy_head=ListNode(next=head)
cur=dummy_head
while cur.next!=None:
if cur.next.val==val:
cur.next=cur.next.next
else:
cur=cur.next
return dummy_head.next
707. 设计链表
- TODO: 把这个题做完。
206. 反转链表
206. 反转链表
分析:原本的顺序是 pre->cur->next,现在要改成 pre<-cur<-next
思考:
- 循环的终止条件是什么?
答:循环到链表结尾,cur 若为空则停止。- 返回值应该写哪个?pre, cur, temp
答:pre,从循环出来时,cur 为None,pre 是最后一轮循环中的cur。
# 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: Optional[ListNode]) -> Optional[ListNode]:
cur=head
pre=None
while cur!=None:
temp=cur.next
cur.next=pre
pre=cur
cur=temp
return pre
24. 两两交换链表中的节点
24. 两两交换链表中的节点
链表的题,最好画出图来,缕清过程,然后再写代码。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy_head=ListNode(next=head)
pre=dummy_head
while pre.next and pre.next.next:
cur=pre.next
post=pre.next.next
# 这几个的赋值顺序一定要理清
cur.next=post.next
post.next=cur
pre.next=post
pre=pre.next.next
return dummy_head.next
19. 删除链表的倒数第 N 个结点
19. 删除链表的倒数第 N 个结点
分析:这个题解挺有趣,用了快慢指针的方法,快慢指针间隔n步,这样快指针到终点时,慢指针为倒数第n个结点。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummy_head=ListNode(next=head)
s,f=dummy_head,dummy_head
while(n!=0):
f=f.next
n-=1
while f.next!=None:
s=s.next
f=f.next
s.next=s.next.next
return dummy_head.next
面试题 02.07. 链表相交
面试题 02.07. 链表相交
这个题解很巧妙,先放代码,后续再好好体会一下。
- TODO: 写个更详细的题解
# 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:
"""
根据快慢法则,走的快的一定会追上走得慢的。
在这道题里,有的链表短,他走完了就去走另一条链表,我们可以理解为走的快的指针。
那么,只要其中一个链表走完了,就去走另一条链表的路。如果有交点,他们最终一定会在同一个
位置相遇
"""
if headA is None or headB is None:
return None
cur_a, cur_b = headA, headB # 用两个指针代替a和b
while cur_a != cur_b:
cur_a = cur_a.next if cur_a else headB # 如果a走完了,那么就切换到b走
cur_b = cur_b.next if cur_b else headA # 同理,b走完了就切换到a
return cur_a
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:
# 初始化快慢指针
fast = slow = head
# 如果不存在环,肯定 fast 先指向 null
# 细节:fast 每次走 2 步,所以要确定 fast 和 fast.next 不为空,不然会报执行出错。
while fast and fast.next:
# 快指针移动 2 步,慢指针移动 1 步
fast = fast.next.next
slow = slow.next
# 快慢指针相遇,有环
if fast == slow:
return True
return False
142. 环形链表 II
142. 环形链表 II
双指针,接下来就是经典的追击问题了。
- TODO:写本题解析
# 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;
fast = head
while slow != fast:
fast = fast.next
slow = slow.next
return slow