题目
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例2:
输入:head = []
输出:[]
示例3:
输入:head = [1]
输出:[1]
代码
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode node = new ListNode(-1, head);
ListNode NewHead = node;
ListNode slow = head;
ListNode fast = head.next;
while (fast != null && fast.next != null) {
ListNode cur = fast.next;
ListNode node1 = slow;
ListNode node2 = fast;
slow = slow.next.next;
fast = fast.next.next;
node1.next = node2.next;
node2.next = node1;
node.next = node2;
node = node1;
}
if (fast == null) {
;
} else {
fast.next = slow;
slow.next = null;
node.next = fast;
}
return NewHead.next;
}
题目解析
这道题的关键就在于,如何交换两个节点,我们举一个例子:
假如一个链表只有两个节点:
我们需要将node1.next赋值成node2.next(node1.next=node2.next),再将node2.next赋值成node1(node2.next=node1),像这样:
注意交换节点的引用也同样发生了变化,这一点需要特别注意。
两个节点交换问题解决了,我们再来看这道题目如何解决。
假设有这样一个链表:
首先我们实例化一个傀儡节点node,这个节点指向head,然后在实例化三个节点NewHead(同样指向head节点),fast(遍历链表,找到交换的节点),slow(遍历节点,找到交换的节点),像这样:
注:NewHead的作用是返回第一个节点(不是头节点),这里我说的时第一个节点,而不是head节点,因为head节点交换过了位置,所以要用NewHead记住第一个节点。
这时候我们在slow和fast的位置,实例化两个节点node1和node2,用于交换节点(交换的过程就是上面分析的过程),然后slow和fast这两个节点往后移动两个节点,node1和node2再进行交换,交换过程就不过多解释了,完成交换后再将node2赋值给node.next(node.next = node2;),最后把node1赋值给node(node = node1;),完成后,链表变成这样。
接下来,因为fast.next为null,所以跳出循环,再交换slow和fast两个节点,完成后,链表变成这样。
可以看到“1”和“4”,没有完成链接,所以我们要将node.next赋值成fast(node.next = fast;)因此我们知道了node的作用就是为了交换两个节点后,把这两个节点与前面的链表相连接,最后完成这道题目。
但是这样是会产生Bug的,第一,当链表只有一个节点,或者为null时,是要单独考虑的,直接返回head就可以了。第二,循环结束后,有两种情况:1、fast为null(奇数情况),2、fast.next为null(偶数情况),当出现奇数情况时,不需要我们考虑,直接返回New.next就可以了;当为偶数情况时,就是上面的交换最后两个节点,再返回NewHead.next就可以了。这样就完成了该题目。
好了,今天的每日一题就到这里了,如果对你有所帮助和启发别忘了点赞,如果有问题或者建议,也欢迎私信评论。谢谢各位!附上今日的LeetCode链接:
附:LeetCode24题——两两交换链表中的节点