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}
.
https://oj.leetcode.com/problems/reorder-list/
思路:分三步走
- 从中间把链表分开(双指针法)
- 把后面的链表反序
- 合并两个链表
public class Solution { public void reorderList(ListNode head) { if (head == null || head.next == null || head.next.next == null) return; ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null && fast.next.next != null) { slow = slow.next; fast = fast.next.next; } ListNode second = slow.next; slow.next = null; second = reverse(second); merge(head, second); } private ListNode reverse(ListNode head) { if (head == null || head.next == null) return head; ListNode pre = head; ListNode cur = head.next; while (cur != null) { ListNode post = cur.next; cur.next = pre; pre = cur; cur = post; } head.next = null; return pre; } private void merge(ListNode first, ListNode second) { ListNode cur1 = first; ListNode cur2 = second; while (cur2 != null) { ListNode post1 = cur1.next; ListNode post2 = cur2.next; cur1.next = cur2; cur2.next = post1; cur1 = post1; cur2 = post2; } } public static void main(String[] args) { ListNode head = makeList(new int[] { 1 }); printList(head); new Solution().reorderList(head); printList(head); } private static ListNode makeList(int[] a) { ListNode head = new ListNode(-1); ListNode p = head; for (int i = 0; i < a.length; i++) { p.next = new ListNode(a[i]); p = p.next; } return head.next; } private static void printList(ListNode head) { ListNode p = head; while (p != null) { System.out.print(p.val); if (p.next != null) System.out.print("->"); p = p.next; } System.out.println(); } }
第二遍记录:
reverse 再练习下,画图分析下,开始写错了。
private ListNode reverse(ListNode head) { ListNode dummyHead = new ListNode(-1); dummyHead.next = head; ListNode pre = head; ListNode cur = head.next; while(cur!=null){ ListNode post=cur.next; pre.next=post; cur.next=dummyHead.next; dummyHead.next=cur; cur=post; } return dummyHead.next; }
第三遍记录:思路不变,注意细节。
reverse的时候 最后head.next要至为null
merge也比较简单,犯了个低级失误,指针变换的时候要赋值出去的指针记得要先复制出去,否则自己被改变了,再赋值出去就不对了,说的有点乱,总之注意变换的顺序。
public class Solution { public void reorderList(ListNode head) { if (head == null || head.next == null || head.next.next == null) return; ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null && fast.next.next != null) { fast = fast.next.next; slow = slow.next; } ListNode first = head; ListNode second = slow.next; slow.next = null; ListNode revSec = reverse(second); merge(first, revSec); } private ListNode merge(ListNode l1, ListNode l2) { ListNode head = l1; while (l1 != null && l2 != null) { ListNode l1Next = l1.next; ListNode l2Next = l2.next; l2.next = l1.next; l1.next = l2; l1 = l1Next; l2 = l2Next; } return head; } private ListNode reverse(ListNode head) { if (head == null || head.next == null) return head; ListNode newHead = new ListNode(-1); newHead.next = head; ListNode cur = head.next; while (cur != null) { ListNode post = cur.next; cur.next = newHead.next; newHead.next = cur; cur = post; } head.next = null; return newHead.next; } public static void main(String[] args) { ListNode head = ListUtils.makeList(1, 2, 3, 4, 5); ListUtils.printList(head); new Solution().reorderList(head); ListUtils.printList(head); } }
参考:
http://www.programcreek.com/2013/12/in-place-reorder-a-singly-linked-list-in-java/
http://codeganker.blogspot.com/2014/03/reorder-list-leetcode.html