开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情
给定一个单链表 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
思路
单链表查找只能顺着链表方向,读完题目之后,我们发现偶数结点的n、n-1这部分是逆序的,为了挨个遍历这部分并插入,我们需要找到这些结点,并将其翻转。
从哪里开始翻转呢,奇数和偶数各占一半,因此我们只需要找到中间结点即可。当然,总数如果是奇数,找到是最中间的结点,为偶数,找到后一半的第一个结点。怎么找?用双指针法,前一个指针每次走一步,后一个指针每次走两步,后一个指针走到最后,第一个指针刚好找到中间结点。
随后,我们将前一半顺序的结点和后一半逆序的结点合并成一个链表即可。
代码
if (head == null) {
return;
}
//存到 list 中去
List<ListNode> list = new ArrayList<>();
while (head != null) {
list.add(head);
head = head.next;
}
//头尾指针依次取元素
int i = 0, j = list.size() - 1;
while (i < j) {
list.get(i).next = list.get(j);
i++;
//偶数个节点的情况,会提前相遇
if (i == j) {
break;
}
list.get(j).next = list.get(i);
j--;
}
list.get(i).next = null;
}
总结
本题要重排链表,观察案列可发现规律,只需要借助快慢指针找到链表中间节点,把后半段链表反转后,合并前半段链表,即可得出答案。