一、题目
前置题目
力扣 206.反转链表
力扣 876. 链表的中间结点
二、思路
观察链表发现链表是部分有序,奇数位置的节点组成前半段的原链表,偶数位置的节点组成后半段的反转链表。因此,首先需要找到中间节点(力扣 876. 链表的中间结点),将原链表分为前半段和后半段链表,再将后半段链表进行反转(力扣 876. 链表的中间结点),再将两个链表按次序合并即可。
三、代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public void reorderList(ListNode head) {
// 寻找中间节点
ListNode mid = midNode(head);
// 将 mid 之后的链表作为一个新的链表 l2
ListNode l2 = mid.next;
// 将 head 至 mid 作为新链表 l1
ListNode l1 = head;
mid.next = null;
// 反转 l2
l2 = reverseList(l2);
// 合并 l1 和 l2
mergeList(l1, l2);
}
// 寻找中间节点
public ListNode midNode(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
// 反转链表
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
ListNode curNext = cur.next;
cur.next = pre;
pre = cur;
cur = curNext;
}
return pre;
}
// 合并链表
public void mergeList(ListNode l1, ListNode l2) {
ListNode l1_tmp, l2_tmp;
while (l1 != null && l2 != null) {
l1_tmp = l1.next;
l2_tmp = l2.next;
l1.next = l2;
l2.next = l1_tmp;
// 更新
l2 = l2_tmp;
l1 = l1_tmp;
}
}
}