<LeetCode(Java版)>Reorder List

来源:互联网 发布:支付宝mac客户端下载 编辑:程序博客网 时间:2024/05/17 04:23

题目:

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)
  此题要求在不改变节点value值的情况下,写出完整代码,给我的第一感觉就是又是乱七八糟的指针操作(对于指针操作,一般需要缓存当前访问的节点,当前访问节点的next节点等等)。看到这道题,给我的第一直觉就是如果能用栈去缓存,然后一边出栈,一边移动链表指针,这样问题就解决了,于是第一版的思路出来了。

public void reorderList(ListNode head) {        if(head == null)            return;        Stack<ListNode> stack = new Stack<ListNode>();        ListNode node = head;        int elementNum = 0;        //将所有元素入栈        while(node !=null){            stack.push(node);            node = node.next;            elementNum++;        }        ListNode nowPos = head;        ListNode nextPos = null;        ListNode tailPos = null;        for(int i = 0;i<elementNum/2;i++){            if(tailPos != null)                tailPos.next = nowPos;            nextPos = nowPos.next;            tailPos = stack.peek();            nowPos.next = stack.pop();            nowPos= nextPos;        }    }

  但这套代码在LeetCode显示Memory Limit Exceeded,也就是说,此种方法内存开销会相当大,那么有没有另外的解决办法呢?
思路(2):
  其实细心的盆友就可以看出来,将所有元素入栈是极大的浪费,因为我们需要反转的就是后半部分,但不是用Stack去缓存链表,而是直接操作链表反转,这样第二种思路就出现了。

        public void reorderList(ListNode head) {              if (head == null || head.next == null) return;              //把整个链表划分成2个等长的子链表,如果原链表长度为奇数,那么第一个子链表的长度多1              ListNode slow = head, fast = head;              while (fast.next != null) {                  fast = fast.next;                  if (fast.next != null) fast = fast.next;                  else break;                  slow = slow.next;              }              ListNode head1 = head, head2 = slow.next;              slow.next = null;              //翻转第二个子链表              ListNode cur = head2, post = cur.next;              cur.next = null;              while (post != null) {                  ListNode tmp = post.next;                  post.next = cur;                  cur = post;                  post = tmp;              }              head2 = cur;              //将两个子链表合并              ListNode node1 = head1, node2 = head2;              while (node2 != null) {                  ListNode tmp1 = node1.next;                  ListNode tmp2 = node2.next;                  node1.next = node2;                  node2.next = tmp1;                  node1 = tmp1;                  node2 = tmp2;              }          } 

  LeetCode上显示Runtime: 384 ms,Your runtime beats 97.45% of java coders.性能相当不错了。其实这题还有其它的思路,有兴趣的可以思索一下。

0 0
原创粉丝点击