[LeetCode题解]143. 重排链表 | 快慢指针 + 反转
解题思路
找到右边链表,再反转右边链表,然后按左、右逐一合并
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* public int val;
* public ListNode next;
* public ListNode(int val=0, ListNode next=null) {
* this.val = val;
* this.next = next;
* }
* }
*/
public class Solution {
public void ReorderList(ListNode head) {
// 找到右边链表,再反转,然后逐一合并
if(head == null || head.next == null) {
return;
}
// 找到右边链表
ListNode fast = head, slow = head;
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
ListNode rightHead = slow.next;
slow.next = null; // 拆分左右两链表
ListNode left = head;
ListNode right = Reverse(rightHead); // 反转右边链表
// 使用虚拟头,按左、右逐一合并
ListNode dummy = new ListNode();
ListNode cur = dummy;
while(left != null && right != null) {
cur.next = left;
cur = cur.next;
left = left.next;
cur.next = right;
cur = cur.next;
right = right.next;
}
cur.next = left != null ? left : right;
head = dummy.next; // 最后把 head 指向新的链表的头
}
private ListNode Reverse(ListNode head) {
ListNode cur = head, pre = null;
while(cur != null) {
var nextTmp = cur.next;
cur.next = pre;
pre = cur;
cur = nextTmp;
}
return pre;
}
}
复杂度分析
- 时间复杂度:\(O(n)\),其中 \(n\) 是链表长度。相当于进行了两次遍历,因此时间复杂度为 \(O(n)\)。
- 空间复杂度:\(O(1)\)。只使用了几个节点指针。