Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You must do this in-place without altering the nodes' values.
For example,
Given {1,2,3,4}
, reorder it to {1,4,2,3}
.
这道题的思路是
1,将链表从中间分成两个。
2,对后面的链表进行Reverse。
3,将两个链表交替合并。
我一开始采用递归实现,结果StackOverFlow了,这是由于递归的空间复杂度为O(N)。代码如下。
public class ReOrderList2 {
ListNode end = null;
private ListNode reverseList(ListNode head){
if(head.next != null){
ListNode temp = reverseList(head.next);
temp.next = head;
head.next = null;
}else{
end = head;
}
return head;
}
private ListNode mergeList(ListNode l1, ListNode l2){
ListNode head = l1 , prevL1 = null, prevL2 = null;
while(l1!= null && l2 != null){
prevL1 = l1;
prevL2 = l2;
ListNode temp1 = l1.next;
l1.next = l2;
l1 = l2 ;
l2 = temp1;
}
// if(l2 == null) prevL1.next = l1;
// if(l1 == null) prevL2.next = l2;
return head;
}
public void reorderList(ListNode head) {
if(head == null || head.next == null) return ;
ListNode fast = head, slow = head, prev = null;
while(fast != null && fast.next != null){
fast = fast.next.next;
prev = slow;
slow = slow.next;
}
if(prev != null)prev.next = null;
reverseList(slow);
mergeList(head, end);
}
}
那就将递归改成递推,使得空间复杂度降低为O(1)。
public class Solution {
private ListNode reverseList(ListNode head){
ListNode tail = head;
if(head.next == null) return head;
ListNode prev =head, cur =head.next, next = cur.next;
while(cur != null){
next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
tail.next = null;
return prev;
}
private ListNode mergeList(ListNode l1, ListNode l2){
ListNode head = l1;
while(l1!= null && l2 != null){
ListNode temp1 = l1.next;
l1.next = l2;
l1 = l2 ;
l2 = temp1;
}
return head;
}
public void reorderList(ListNode head) {
if(head == null || head.next == null) return ;
ListNode fast = head, slow = head, prev = null;
while(fast != null && fast.next != null){
fast = fast.next.next;
prev = slow;
slow = slow.next;
}
if(prev != null)prev.next = null;
ListNode last = reverseList(slow);
mergeList(head, last);
}
}
上述两个算法的整体时间复杂度均为O(1).