题目链接:24. 两两交换链表中的节点 - 力扣(LeetCode)
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
如结点值原本按顺序是【1,2,3,4】交换结果的顺序就是【2,1,4,3】
做法一:
不能改变值只能换位置,即你只能改变next。
交换思路:
用move和p来指向当前未进行交换操作的先后一对两个结点
然后分成以下两种情况:
1. 这一对之后还有一对要换 如 【1,2,3,4】12交换之后还有34要交换
这种情况比较复杂,因为12交换之后,后续34交换,那么1的后续结点应该是4,而不是原本2的后续“3”。
这种情况下如果单纯使用
move.next = p.next
p.next = move
move = p.next
那么交换后 2 1 3 4 进行交换后 1.next 仍是3。
所以我们应该直接一步到位 当我们发现这一对之后还有一对:即 p.next and p.next.next都不为空
那么我们就直接让第一个结点next指向第四个结点。因为如果不直接连向第四个结点,而是只是连接到原本第二个结点的下一个结点也就是第三个结点,那么下一轮34切换之后,我们还得把1的后续结点从3改为4,但是我们的结点并没有“前指针”,相当于关于1的结点信息就此丢失,后续如果硬要操作的话,还得使用更多的空间。
if p.next and p.next.next:
t = p.next
move.next = p.next.next
p.next = move
move = t
我们在改变p的next时先将p.next保存为t,避免结点的指向信息丢失
2. 这一对之后没有下一对要交换 如【1,2】和【1,2,3】
这种情况下,12对换,后续并没有下一对进行对换,也就是说,1的后续结点直接放心的变成2的后续结点就好。不用担心2的后续结点会变换位置。
else:
t =p.next
move.next = p.next
p.next = move
move = t
整体代码:
# 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: ListNode) -> ListNode:
if not head:return None # 输入空结点直接返回空
if not head.next:return head # 单独输入一个结点返回该结点
move = head
head = head.next # 原本第二个结点是结果的头节点
while move and move.next: # 当未到达最后一个结点时
p = move.next
if p.next and p.next.next:
t = p.next
move.next = p.next.next
p.next = move
move = t
else:
t =p.next
move.next = p.next
p.next = move
move = t
# 执行交换操作,注意题目要求不能改变值,所以只能改变next
return head