赞
踩
这道题目总的来说可以分三步,第一步是找到Linked List的中点,第二部是翻转Linked List的后半部分,第三部就是把Linked List按照题目的要求进行reorder,现在大的思路已经明确,接下来我们所需要的就是思考这三步怎样实现。
1->2->3->4->5->6
首先第一步的话,我们可以使用slow runner/fast runner来实现。对于第二步来说,假设题目中的Linked List如上面所示,第二步我们所要做的就是将上面的Linked List翻转成下面所示的:
1->2->3->6->5->4
这一步我们也是之前的一个题目,我们可以使用两个指针进行实现。
现在Linked List已经如上面的所示,我们可以使用三个指针:slow指向3,p1指向1,p2指向6;然后一步一步进行翻转,翻转的代码已经在下面给出,可以根据代码进行理解,关键问题是这个循环的终止条件是什么。通过对Linked List长度为奇数和偶数情况的分析,我们可以得到循环的终止条件为p1和p2中间有一个为空,或者有一个更为巧妙些的循环条件是slow == p1。整体的代码如下:
- /**
- * Definition for singly-linked list.
- * public class ListNode {
- * int val;
- * ListNode next;
- * ListNode(int x) { val = x; }
- * }
- */
- public class Solution {
- public void reorderList(ListNode head) {
- if(head == null || head.next == null) return;
-
- // Find the middle of the list
- ListNode slow = head;
- ListNode fast = head;
- while(fast.next != null && fast.next.next != null){
- slow = slow.next;
- fast = fast.next.next;
- }
-
- // Reverse last half of linked list
- slow.next = reverseList(slow.next);
-
- // Reorder one by one
- ListNode p1 = head;
- ListNode p2 = slow.next;
- while(p1 != null && p2 != null){
- slow.next = p2.next;
- p2.next = p1.next;
- p1.next = p2;
- p1 = p1.next.next;
- p2 = slow.next;
- }
- }
-
- private ListNode reverseList(ListNode head){
- ListNode prev = null;
- ListNode curr = head;
- ListNode next = null;
-
- while(curr != null){
- next = curr.next;
-
- curr.next = prev;
- prev = curr;
- curr = next;
- }
-
- return prev;
- }
- }
思考:
1. 这道题目综合了一些非常基础的题目,所以对于基础类型的题目一定要掌握好,它们可能是解决更为复杂问题的阶梯
2. 这道题目使用了一种翻转的思想,就是对题目中的输入进行某种程度的翻转,从而达到更容易解决问题的目的;还有一种大翻转也同样经常使用,就是对整体进行reverse之后再对某些个体进行reverse,而不是谨小慎微地单单翻转某些个体,这种思想非常重要
3. 这道题目也是一个非常典型的Linked List题目,多多反复看看会有新的发现
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。