题解 | #重排链表#
重排链表
https://www.nowcoder.com/practice/3d281dc0b3704347846a110bf561ef6b
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public void reorderList(ListNode head) {
if (head == null || head.next == null || head.next.next == null) return;
// 重排为:0, n, 1, n-1, 2, n-2
/*
解题思路:
1.先使用快慢指针,找到链表的中间节点
2.将后半部分的链表反转(双指针局部反转)
3.将两个链表合并
*/
// 1.快慢指针找到中间节点
ListNode fast = head, slow = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
ListNode midHead = slow.next; // 下半部分的头节点
slow.next = null; // 释放节点
// 2.反转后半部分链表
midHead = reverseList(midHead); // 个数少于前半部分或等于前半部分
// 3.链表合并
while (midHead != null) {
ListNode temp = midHead.next;
midHead.next = head.next;
head.next = midHead;
head = midHead.next;
midHead = temp;
}
}
// 链表反转
private ListNode reverseList(ListNode head) {
if (head == null) return null;
ListNode tail = head;
head = head.next;
tail.next = null; // 链表(尾部)头部指向 null
while (head != null) {
ListNode temp = head.next;
head.next = tail; // 指针反转
// 都向前走一个节点
tail = head;
head = temp;
}
return tail;
}
}
可以先使用快慢指针找到中间节点,然后将后半部分的链表通过双指针迭代进行反转,最后将两部分链表进行合并即可。
时间复杂度O(N):N表示链表长度,双指针一次遍历
空间复杂度O(1):常数大小空间指针
查看14道真题和解析