难度:中等
频次:143
题目:给定一个单链表 L 的头节点 head ,单链表 L 表示为:
请将其重新排列后变为:
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
解题思路:链表找中间节点+链表反转+链表连接
注意:
- 中间节点并不是我们真正想要的,我们想要的是两个链表
- 而且前面的链表长,后面的链表需要是从中间节点的下一个节点开始
- 需要注意断开链表(不然会体现除循环链表)
- 是通过中间节点,而不是通过奇数
代码:
/**
* 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) {
//如果链表长度为1,直接返回
if(head.next==null) return;
ListNode dummyhead=new ListNode(-1);
dummyhead.next=head;
//找出中间节点
ListNode middleNode=middleNode(head);
//第二个链表的头节点newhead
ListNode newhead;
newhead=middleNode.next;
//断开两个链表
middleNode.next=null;
newhead=reversal(newhead);
merge(head,newhead);
}
//反转链表
public ListNode reversal(ListNode head){
ListNode dummyhead =new ListNode(0);
dummyhead.next=head;
ListNode g=dummyhead,p=head;
while(p.next!=null){
ListNode temp=p.next;
p.next=temp.next;
temp.next=g.next;
g.next=temp;
}
return dummyhead.next;
}
//找到中间节点(如果偶数,则是后面那个)
public ListNode middleNode(ListNode head) {
ListNode fast=head,slow=head;
while(fast.next!=null&&fast.next.next!=null){
slow=slow.next;
fast=fast.next.next;
}
return slow;
}
public void merge(ListNode head,ListNode newhead){
ListNode temp1;
ListNode temp2;
while(head!=null&&newhead!=null){
//标记下一个节点
temp1=head.next;
temp2=newhead.next;
//连接过程
newhead.next=temp1;
head.next=newhead;
//使head newhead指向下一个节点
head=temp1;
newhead=temp2;
}
}
}