1. 题目
https://leetcode.cn/problems/reorder-list/
考察点
- 这道题的考察点是链表的操作,包括找到链表的中点,反转链表,合并链表等。这些操作都是链表的基本技巧,需要熟练掌握
- 这道题也可以看作是一个数学问题,就是如何把一个序列重新排列成另一个序列,满足一定的规律。这里的规律是把序列分成两部分,然后交替取元素。这种问题可以用递归或者迭代的方法来解决。
- 这道题还可以考察你的编程能力,比如如何写出清晰,高效,可读的代码,如何处理边界情况,如何优化空间和时间复杂度等
2. 解法
解法的思路
- 首先用快慢指针找到链表的中点,把链表分成两部分。
- 然后反转后半部分的链表,这样就可以从两端向中间遍历。
- 最后交替合并两个链表,把后半部分的节点插入到前半部分的节点之间。
代码逻辑
代码的逻辑。代码分为三个步骤:
- 第一步是找到链表的中点,把链表分成两部分。这里用了一个快慢指针的技巧,快指针每次走两步,慢指针每次走一步,当快指针到达链表尾部时,慢指针就是中点。例如,对于链表1->2->3->4->5,快指针会走到5,慢指针会走到3,所以链表可以分成1->2->3和4->5两部分。
- 第二步是反转后半部分的链表,这样就可以从两端向中间遍历。这里用了一个常见的反转链表的方法,用一个prev指针记录前一个节点,一个curr指针记录当前节点,然后不断更新curr.next = prev,prev = curr,curr = curr.next,直到curr为空。例如,对于链表4->5,反转后变成5->4。
- 第三步是交替合并两个链表,把后半部分的节点插入到前半部分的节点之间。这里用了两个指针first和second分别指向两个链表的头节点,然后不断更新first.next = second,first = first.next,second.next = first,second = second.next,直到second.next为空。例如,对于链表1->2->3和5->4,合并后变成1->5->2->4->3。
这样就完成了重新排列链表的任务。
具体实现
public class Solution { public void reorderList(ListNode head) { if (head == null || head.next == null) return; // 找到链表的中点 ListNode slow = head, fast = head; while (fast.next != null && fast.next.next != null) { slow = slow.next; fast = fast.next.next; } // 反转后半部分的链表 ListNode prev = null, curr = slow.next; while (curr != null) { ListNode next = curr.next; curr.next = prev; prev = curr; curr = next; } // 合并两个链表 ListNode first = head, second = prev; while (second.next != null) { ListNode next = first.next; first.next = second; first = next; next = second.next; second.next = first; second = next; } } }