题目
给定一个单链表 L
的头节点 head
,单链表 L
表示为:
L0 → L1 → … → Ln - 1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入:head = [1,2,3,4] 输出:[1,4,2,3]
示例 2:
输入:head = [1,2,3,4,5] 输出:[1,5,2,4,3]
提示:
- 链表的长度范围为
[1, 5 * 104]
1 <= node.val <= 1000
解答
源代码
/**
* 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) {
if (head.next == null) {
return;
}
ListNode middleList = searchMiddleList(head);
ListNode reversedList = reverse(middleList);
ListNode res = linkList(head, reversedList);
}
// 寻找中间节点
public ListNode searchMiddleList(ListNode head) {
ListNode pre = new ListNode(0);
ListNode fast = head, slow = head;
pre.next = slow;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
pre = pre.next;
}
// 将前半部分链表结尾置空
pre.next = null;
return slow;
}
// 反转链表
public ListNode reverse(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
// 交替拼接两个链表
public ListNode linkList(ListNode head1, ListNode head2) {
ListNode dummy = new ListNode(0);
ListNode temp = dummy;
while (head1 != null && head2 != null) {
temp.next = head1;
head1 = head1.next;
temp = temp.next;
temp.next = head2;
head2 = head2.next;
temp = temp.next;
}
if (head1 == null) { // head1已经拼接完毕
temp.next = head2;
} else { // head2已经拼接完毕
temp.next = head1;
}
return dummy.next;
}
}
总结
讨论区提供的思路:快慢指针找中间节点、将中间节点对应的后部分反转、将两条链表交替连接。这道题很综合,用到之前的很多知识点,代码是自己慢慢写的,确实很好地锻炼了动手能力。