携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第25天,点击查看活动详情
痛苦周二,截止至今依旧没有拿到画的大饼任务
重排链表
该题出自力扣的143题 —— 重排链表【中等题】,确实是很经典的链表题型
审题
- 该题的题意并不复杂,但是相当经典,因为可以一题3用,一道题复习了链表的3个基础
- 其实就是给出一个链表的头结点,然后返回重新排序后的链表,并且需要按照特定的顺序,1, n , 2, n-1......的顺序
- 那么这道题有几个解题点
- 拆分:首先交错的排序,就需要把链表分成两组,正序一组,倒序一组
- 倒序:正序的分为一组,另一组就需要进行倒序
- 合并:对两个链表进行合并成一个链表
- 那么根据这几个解题点就可以分成对应的函数方法
- 首先找到链表的中点
- 利用快慢指针,快指针比慢指针快一倍,最终快指针走到结尾null的时候,慢指针也就到达中点
- 反转链表
- 利用一个链表空值,作为链表的反转,依次取到链表的下一个,并且反转
- 从中点的下一个节点开始反转
- 合并
- 首先对链表的进行遍历,合并也就是交叉合并,因为题意所提及的是交叉编排
- 首先找到链表的中点
编码
class Solution {
public void reorderList(ListNode head) {
// 寻找链表中点
ListNode mid = findMid(head);
// 反转链表
ListNode first = head;
ListNode second = mid.next;
mid.next = null;
second = reverse(second);
// 合并链表
mergeNode(first,second);
}
private void mergeNode(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;
l1 = l1_tmp;
l2.next = l1;
l2 = l2_tmp;
}
}
private ListNode reverse(ListNode mid) {
ListNode result = null;
ListNode p = mid;
while (p != null){
ListNode a = p.next;
p.next = result;
result = p;
p = a;
}
return result;
}
private ListNode findMid(ListNode head) {
ListNode first = head,second = head;
while (second.next != null && second.next.next != null){
first = first.next;
second = second.next.next;
}
return first;
}
}