给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln - 1 → Ln
请将其重新排列后变为:L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。示例 1:
输入:head = [1,2,3,4]
输出:[1,4,2,3]
示例 2:输入:head = [1,2,3,4,5]
输出:[1,5,2,4,3]提示:
链表的长度范围为 [1, 5 * 104]
1 <= node.val <= 1000
这个题两种解法
第一种:
我们定义一个线性表,先把链表的结点都放进去,然后根据题目要求的顺序,操作链表的next指向即可
为什么选择线性表呢?
从题目我们可以看到 题目要求我们 第一个指向最后一个 在指向低二个在指向倒数第二个…
这就必须要求我们能 定位链表结点
所以用线性表就可以根据下标快速定位到目标结点
时间复杂度 O(N)
空间复杂度 O(N)
第二种方法:比较综合基础
观察题目我们可以发现,如果我们找到中中间结点,将中间节点一分为二,然后右边的再反转,然后再将左右两边的链表合并,那么就是目标顺序链表了
所以我们要做的工作就是
- 找到中间结点
- 反转链表
- 合并链表
时间复杂度 O(N)
空间复杂度 O(1)
所以这种方法是第一种方法的优化
法一
/**
* 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) {
List<ListNode> res=new ArrayList<>();
ListNode cur=head;
while(cur!=null){
res.add(cur);
cur=cur.next;
}
int begin=0;
int end=res.size()-1;
while(begin!=end){
res.get(begin).next=res.get(end);
begin++;
if(begin==end){
break;
}
res.get(end).next=res.get(begin);
end--;
}
res.get(begin).next=null;
}
}
法二
/**
* 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 mid=findMid(head);
ListNode midNext=mid.next;
mid.next=null;
ListNode head2=reverse(midNext);
head=mergeListNode(head,head2);
}
public ListNode findMid(ListNode head){
ListNode slow=head,fast=head;
while(fast.next!=null && fast.next.next!=null){
slow=slow.next;
fast=fast.next.next;
}
return slow;
}
public ListNode reverse(ListNode head){
ListNode pre=head,cur=null;
while(pre!=null){
ListNode next=pre.next;
pre.next=cur;
cur=pre;
pre=next;
}
return cur;
}
public ListNode mergeListNode(ListNode head1,ListNode head2){
ListNode newHead=new ListNode();
ListNode tail=newHead;
ListNode r1=head1,r2=head2;
while(r1!=null && r2!=null){
tail.next=r1;
tail=r1;
r1=r1.next;
tail.next=r2;
tail=r2;
r2=r2.next;
}
tail.next=r1==null?r2:r1;
return newHead.next;
}
}