题目
Given a linked list, swap every two adjacent nodes and return its head.
You may not modify the values in the list's nodes, only nodes itself may be changed.
Example:
Given 1->2->3->4, you should return the list as 2->1->4->3.
解法思路(一)
两两交换过程图示
两两交换过程描述
- 链表中的节点在交换位置的时候,要坚持一个原则:链表不能断开;
- 交换链表中两个相邻节点 a(cur) 和 b 的位置,就要依赖 a(cur) 的前驱
pre
和后继post
,但头节点是没有前驱的,所以在链表的头节点前加上虚拟头节点,使对链表中的每个节点的操作都一致,无需针对头节点做特殊处理; - 交换链表中两个相邻节点的动作如下:
pre.next = post;
cur.next = post.next;
post.next = cur;
解法实现(一)
时间复杂度
- O(N);
空间复杂度
- O(1);
关键字
链表节点交换
实现细节
- 注意虚拟头节点的创建;
- 在遍历开始前,要确定好每个游标的位置:
pre
,cur
,post
;
package leetcode._24;
public class Solution24_1 {
public ListNode swapPairs(ListNode head) {
ListNode dumyHead = new ListNode(0);
dumyHead.next = head;
ListNode pre = dumyHead;
ListNode cur = head;
while (cur!= null && cur.next != null) {
ListNode post = cur.next;
pre.next = post;
cur.next = post.next;
post.next = cur;
pre = cur;
cur = cur.next;
}
return dumyHead.next;
}
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4};
ListNode head = new ListNode(arr);
System.out.println(head.toString());
ListNode head2 = (new Solution24_1()).swapPairs(head);
System.out.println(head2);
}
}
解法思路(二)
链表中两个节点交换示意图
链表中两个节点交换描述
- 不同于解法思路(一),此解法将一次交换中涉及到的所有节点都用指针标出(指着),是为了防止指针变化指向的时候,丢失节点;
- 此解法和解法思路(一)的指针变化过程也有不同,具体如下:
node2.next = node1;
node1.next = post;
pre.next = node2;
解法实现(二)
时间复杂度
- O(N);
空间复杂度
- O(1);
关键字
链表节点交换
实现细节
- 指针变换中所有涉及到的所有节点,都需要用一个引用指着,为的是防止因指针的变化导致节点丢失;
package leetcode._24;
public class Solution24_2 {
public ListNode swapPairs(ListNode head) {
ListNode dummyHead = new ListNode(0);
dummyHead.next = head;
ListNode pre = dummyHead;
while (pre.next != null && pre.next.next != null) {
ListNode node1 = pre.next;
ListNode node2 = node1.next;
ListNode post = node2.next;
node2.next = node1;
node1.next = post;
pre.next = node2;
pre = node1;
}
return dummyHead.next;
}
}