链表重排序算法详解:字节跳动面试题的完整解析
·
链表重排序算法详解:字节跳动面试题的完整解析
问题背景
字节跳动的技术面试中经常出现链表操作题目。这道重排序问题考查了多个核心知识点。面试官希望看到最优解法和清晰的思路分析。
题目内容
我们有一个单链表 L:L0→L1→…→Ln-1→Ln。要把它重新排列成:L0→Ln→L1→Ln-1→L2→Ln-2→…
注意,我们不能简单修改节点的值。需要真正交换节点的位置。
看几个例子:
例子1:
原链表:1→2→3→4→5
结果:1→5→2→4→3
例子2:
原链表:1→2→3→4
结果:1→4→2→3
解题思路分析
这道题目包含了链表操作的几个经典技巧。我们需要观察最终结果的规律。
仔细看重排后的链表,它其实是两部分的交错拼接:
- 前半部分保持原顺序
- 后半部分反转后与前半部分交替连接
这样我们就有了清晰的解题步骤:
- 找到链表的中点
- 把后半部分反转
- 把两部分交错合并
具体实现方法
第一步:寻找链表中点
我们用快慢指针来找中点。设置两个指针 slow 和 fast,都从头开始。
// slow 每次走一步,fast 每次走两步
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
当 fast 到达末尾时,slow 就指向了中点。
对于链表 1→2→3→4→5→6:
- slow 最终指向节点 3
- 前半部分:1→2→3
- 后半部分:4→5→6
第二步:反转后半部分
我们把中点后面的链表反转过来。使用标准的链表反转算法:
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
第三步:交错合并两个链表
现在我们有了两个链表:
- 左边:1→2→3
- 右边:6→5→4(已反转)
我们把它们交错连接起来:
while (leftHead != null && rightHead != null) {
// 保存下一个要处理的节点
ListNode leftNext = leftHead.next;
ListNode rightNext = rightHead.next;
// 连接当前节点
leftHead.next = rightHead;
rightHead.next = leftNext;
// 移动到下一个节点
leftHead = leftNext;
rightHead = rightNext;
}
完整代码实现
class Solution {
public void reorderList(ListNode head) {
// 找到链表中点
ListNode mid = findMiddle(head);
// 分割链表
ListNode leftHead = head;
ListNode rightHead = mid.next;
mid.next = null;
// 反转右半部分
rightHead = reverseList(rightHead);
// 交错合并
mergeLists(leftHead, rightHead);
}
// 寻找链表中点
public ListNode findMiddle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
// 反转链表
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
// 交错合并两个链表
public void mergeLists(ListNode left, ListNode right) {
while (left != null && right != null) {
ListNode leftNext = left.next;
ListNode rightNext = right.next;
left.next = right;
right.next = leftNext;
left = leftNext;
right = rightNext;
}
}
}
核心技术要点
时间复杂度: O(n),我们遍历链表三次(找中点、反转、合并)
空间复杂度: O(1),只用了几个额外的指针变量
关键技巧:
- 快慢指针找中点是链表题的经典方法
- 递归反转链表要注意断开原有连接
- 合并时要先保存下一个节点的位置
这道题目综合运用了链表操作的多个核心技术。掌握了这些基础技巧,面对其他链表问题也会更有信心。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)