LeetCode 24 两两交换链表中的节点
一、题目. - 力扣(LeetCode)
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
二、自己写(看完视频后自己写感觉可以写出来)
# 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]:
dummyhead = ListNode(next=head)
cur = dummyhead
while cur.next != None and cur.next.next != None: # 这里容易错,cur在两个交换节点的前一个节点,所以这里的判断条件是cur的下一个和下下一个都不为None
temp = cur.next
temp1 = cur.next.next.next
cur.next = cur.next.next
cur.next.next = temp
temp.next = temp1
cur = cur.next.next
return dummyhead.next
三、链表需要画图分析
初始时,cur指向虚拟头结点,然后进行如下三步:
操作之后,链表如下:
看这个可能就更直观一些了:
19.删除链表的倒数第N个节点
一、题目:. - 力扣(LeetCode)
给你一个链表,删除链表的倒数第 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]:
slow=head
fast=head
for i in range(n):
fast=fast.next
if not fast:
return head.next
while fast.next:
fast=fast.next
slow=slow.next
slow.next=slow.next.next
return head
三、双指针
双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。
面试题 02.07. 链表相交
一,题目:面试题 02.07. 链表相交 - 力扣(LeetCode)
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
图示两个链表在节点 c1
开始相交:
题目数据 保证 整个链式结构中不存在环。
二、自己写(有点难,刚开始想法不对没有意识到两个链表有可能不一样长)
# 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:
lengthA = 0
curA = headA
lengthB = 0
curB = headB
while curA:
curA = curA.next
lengthA += 1
while curB:
lengthB += 1
curB = curB.next
curA = headA
curB = headB
if lengthA > lengthB:
for _ in range(lengthA - lengthB):
curA = curA.next
elif lengthB > lengthA:
for _ in range(lengthB - lengthA):
curB = curB.next
while curA and curB:
if curA == curB:
return curA
else:
curA = curA.next
curB = curB.next
思路:
- 遍历链表,记录每个链表的长度。
- 将两个链表的指针分别移动到相同的位置(使得从这个位置到末尾的节点数相同)。
- 同时从头到尾遍历两个链表,找到最后一个相同的节点
三、快慢法则,双指针
优雅,太优雅了
- 假设链表
A
的长度是m
,链表B
的长度是n
。 - 通过这种切换链表头的操作,两个指针在遍历完两条链表后,都将经历
m + n
的节点。 - 如果链表相交,在他们走完
m + n
个节点后,两个指针将会在相交节点处相遇。 - 如果链表不相交,两个指针将会同时到达链表末尾的
None
,此时我们知道链表不相交。
# 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:
"""
根据快慢法则,走的快的一定会追上走得慢的。
在这道题里,有的链表短,他走完了就去走另一条链表,我们可以理解为走的快的指针。
那么,只要其中一个链表走完了,就去走另一条链表的路。如果有交点,他们最终一定会在同一个
位置相遇
"""
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
根据快慢法则,curA在A+B链表中找B,curB在A+B链表中找A,如果有交点的肯定能找到(好难理解)
142.环形链表II
一,题目. - 力扣(LeetCode)
题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
二,自己写(看了视频讲解后可以试着写一写)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
fast = head
slow = head
while fast and fast.next != None:
fast = fast.next.next
slow = slow.next
if fast == slow: # fast和slow相遇了
index1 = fast # 这个时候快慢指针在一起
index2 = head
while index1 != index2:
index1 = index1.next
index2 = index2.next
return index1
偏难理解
三、环形链表找交点
代码随想录 (programmercarl.com)思路还是看这个吧