题目描述:给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
节点两两交换,递归和非递归大体思路相似,都是第一个节点指向下一次两个交换节点的第一个节点,第二个节点指向第一个节点。
大概如下图所示:
虚线框里就又是一次递归调用,每次递归返回交换之后的第一个节点
方法一:递归
class Solution {
public ListNode swapPairs(ListNode head) {
// 如果没有节点或者只有一个节点就返回
if (head == null || head.next == null) {
return head;
}
ListNode next = head.next;
head.next = swapPairs(next.next);
next.next = head;
return next;
// 此处为了容易理解可以查看注释代码
// ListNode start = head; 交换之后的第二个节点
// ListNode end = head.next; 交换之后的第一个节点
// start.next = swapPairs(end.next); 从下一组两个节点开始相同操作
// end.next = start;
// retrun end; 返回用于前一个递归得到的节点所指向该节点
}
}
方法二:非递归
非递归和递归不同的是,需要创建一个temp指针用来存储上一次交换后的第二个节点,然后让该节点指向本次交换的第一个节点
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode pre = new ListNode(0);
pre.next = head;
// temp记录上一次交换后的第二个节点
ListNode temp = pre;
while(temp.next != null && temp.next.next != null) {
ListNode start = temp.next; // 交换之后为第二个节点
ListNode end = temp.next.next; // 交换之后为第一个节点
// 将上一次交换的第二个节点指向本次交换的第一个节点
temp.next = end;
start.next = end.next;
end.next = start;
// 记录本次交换的第二个节点,用于下一次指向
temp = start;
}
return pre.next;
}
}