重排链表。题意很简单,
Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You may not modify the values in the list's nodes, only nodes itself may be changed.
Example 1:
Given 1->2->3->4, reorder it to 1->4->2->3.Example 2:
Given 1->2->3->4->5, reorder it to 1->5->2->4->3.
思路也很直观,但是代码容易错,算是链表题里面的综合题吧,有链表的快慢指针fast-slow pointer,反转reverse,和merge两个链表三个技能点的考察。找快慢指针的时候记得设一个temp node,因为slow停下的地方会是second half的起点,这个temp指针会停在first half的尾部。
时间O(n)
空间O(1)
JavaScript实现
1 /** 2 * @param {ListNode} head 3 * @return {void} Do not return anything, modify head in-place instead. 4 */ 5 var reorderList = function(head) { 6 if (!head || !head.next) return; 7 let fast = head; 8 let slow = head; 9 while (fast && fast.next) { 10 fast = fast.next.next; 11 slow = slow.next; 12 } 13 let second = reverseList(slow.next); 14 slow.next = null; 15 let first = head; 16 while (second) { 17 let temp = second.next; 18 second.next = first.next; 19 first.next = second; 20 first = first.next.next; 21 second = temp; 22 } 23 }; 24 25 var reverseList = function(head) { 26 let pre = null; 27 while (head !== null) { 28 let next = head.next; 29 head.next = pre; 30 pre = head; 31 head = next; 32 } 33 return pre; 34 };
Java实现
1 class Solution { 2 public void reorderList(ListNode head) { 3 if (head == null || head.next == null) { 4 return; 5 } 6 ListNode temp = null; 7 ListNode slow = head; 8 ListNode fast = head; 9 ListNode l1 = head; 10 while (fast != null && fast.next != null) { 11 temp = slow; 12 slow = slow.next; 13 fast = fast.next.next; 14 } 15 temp.next = null; 16 ListNode l2 = reverse(slow); 17 merge(l1, l2); 18 } 19 20 private ListNode reverse(ListNode head) { 21 ListNode prev = null; 22 while (head != null) { 23 ListNode next = head.next; 24 head.next = prev; 25 prev = head; 26 head = next; 27 } 28 return prev; 29 } 30 31 private void merge(ListNode l1, ListNode l2) { 32 while (l1 != l2) { 33 ListNode n1 = l1.next; 34 ListNode n2 = l2.next; 35 l1.next = l2; 36 if (n1 == null) 37 break; 38 l2.next = n1; 39 l1 = n1; 40 l2 = n2; 41 } 42 } 43 }
另一种Java实现,把getMiddle写成一个函数,注意while循环的部分
1 /** 2 * Definition for singly-linked list. 3 * public class ListNode { 4 * int val; 5 * ListNode next; 6 * ListNode() {} 7 * ListNode(int val) { this.val = val; } 8 * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 9 * } 10 */ 11 class Solution { 12 public void reorderList(ListNode head) { 13 // corner case 14 if (head == null || head.next == null) { 15 return; 16 } 17 // normal case 18 ListNode middle = findMiddle(head); 19 ListNode first = head; 20 ListNode second = middle.next; 21 middle.next = null; 22 second = reverse(second); 23 merge(first, second); 24 } 25 26 private ListNode findMiddle(ListNode head) { 27 ListNode slow = head; 28 ListNode fast = head; 29 while (fast != null && fast.next != null) { 30 slow = slow.next; 31 fast = fast.next.next; 32 } 33 return slow; 34 } 35 36 private ListNode reverse(ListNode head) { 37 ListNode pre = null; 38 while (head != null) { 39 ListNode next = head.next; 40 head.next = pre; 41 pre = head; 42 head = next; 43 } 44 return pre; 45 } 46 47 private void merge(ListNode left, ListNode right) { 48 ListNode leftTemp; 49 ListNode rightTemp; 50 while (left != null && right != null) { 51 leftTemp = left.next; 52 rightTemp = right.next; 53 left.next = right; 54 right.next = leftTemp; 55 left = leftTemp; 56 right = rightTemp; 57 } 58 } 59 }