题目描述
给定一单链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是简单的改变节点内部的值,而是需要实际的进行节点交换。
示例:
**输入:**head = [1, 2, 3, 4]
**输出:**head = [2, 1, 4, 3]
思路分析
这里我们先考虑两个节点间的互换,可以看图1:
图 1
如图1所示,T1
时刻,我们首先考虑对节点[1, 2]进行交换,则需要:
leftP.next
指向rightP.next
;rightP.next
指向leftP
;- 更新
leftP
的前置节点指针;
这里需要注意的是交换[1, 2]时,还要考虑进节点1
的前置节点的更新。
然后,T2
时刻,我们再来看节点对[3, 4], 这里继续罗列:
1.确定节点3
的前置节点(此时应为1
);
2. leftP.next
指向rightP.next
;
3. rightP.next
指向leftP
;
4. 更新leftP
的前置节点指针;
我们已经发现了问题的规律,即首先确定交换对的前置节点,其次交换并更新下一对的前置节点;之后为前移,重复此过程。
步骤罗列
- 初始化两个指针,这里命名为
leftP, rightP
,为统一规则,设置哨兵节点; - 开始迭代,迭代体内为交换和位移;
- 迭代终止条件为两个指针任一为空,返回哨兵节点的下一节点。
解题代码
public static ListNode solutionWithTwoP(ListNode head) {
if (head == null || head.next == null) {
return head;
}
//1. init pointers and dummyHead
ListNode dummyHead = new ListNode(-1);
dummyHead.next = head;
ListNode leftP = head;
ListNode rightP = head.next;
ListNode currHead = dummyHead;
//2. iteration
while (leftP != null && rightP != null) {
// exchange
leftP.next = rightP.next;
rightP.next = leftP;
currHead.next = rightP;
//update pos of currHead
currHead = leftP;
//move forward
leftP = leftP.next;
rightP = leftP == null? null : leftP.next; //attention here
}
return dummyHead.next;
}
复杂度分析
时间复杂度:我们对数据仅进行了一次遍历,所以时间复杂度为O(N);
空间复杂度:我们没有借助额外的容器,所以空间复杂度为常量级O(1)。
GitHub源码
完整可运行文件请访问GitHub。