题解 | #重排链表#
重排链表
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):常数大小空间指针