题目
https://leetcode-cn.com/problems/LGjMqU/
输入一个链表,重新排列链表的节点顺序。例如:
解题思路
根据题意,把链表分成两部分,前半段和后半段。
把后半段链表反转后,再与前半段链表合并,即可求得重排后的链表。
具体过程分成3步:
1.找到链表前半部分。利用快慢指针,快指针每次先走2步,另外慢指针走一步,当块指针到底尾部时,慢指针则刚好到达链表中间节点。
2.把后半部分链表反转。
3.合并前半部分和反转后的后半部分链表。
具体代码如下:
代码
/**
* 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) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode slow = dummy;
ListNode fast = dummy;
//找到前半段最后一个节点。
while(fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next;
if(fast.next != null) {
fast = fast.next;
}
}
ListNode temp = slow.next;
slow.next = null;
//合并链表
link(head, reverseList(temp), dummy);
}
private void link(ListNode node1, ListNode node2, ListNode head) {
//1 2 3
//5 4
ListNode pre = head; //哨兵节点,用于合并链表。
while(node1 != null && node2 != null) {
ListNode temp = node1.next;
pre.next = node1;
node1.next = node2;
pre = node2;
node1 = temp;
node2 = node2.next;
}
if(node1 != null){ //当链表为奇数数,判断前半部分尾节点。
pre.next = node1;
}
}
private ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while(cur != null) {
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
}
总结
本题要重排链表,观察案列可发现规律,只需要借助快慢指针找到链表中间节点,把后半段链表反转后,合并前半段链表,即可得出答案。