leetcode oj Reorder List

题目:

  Given a singly linked list LL0L1→…→Ln-1Ln,
  reorder it to: L0LnL1Ln-1L2Ln-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}

  要求将链表按如上要求排序,不能修改结点的值,且空间复杂度为O(1)。

一、最简单的实现方法

  先不考虑空间复杂度,考虑怎么实现再说,首先我想到的是递归,将一个链表的最后一个结点挂在第一个结点后面,再递归处理中间的部分。代码如下:

class Solution:
    # @param head, a ListNode
    # @return nothing
    def reorderList(self, head):
        if head is None or head.next is None or head.next.next is None:
            return head
        node = head.next
        while node.next.next is not None:
            node = node.next
        new_head = head.next
        end = node.next
        node.next = None
        head.next = end
        end.next = self.reorderList(new_head)
        return head

  递归的深度是n-2,链表稍微长一点就报错了。

二、更近一步

  上面递归的方法不可行,但也给我们提供一个思路,不容递归我们可以用栈来处理,链表的后半部分压栈,然后出栈与前面部分合并,最后注意一下原链表是基数和偶数的区别:  

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    # @param head, a ListNode
    # @return nothing
    def reorderList(self, head):
        if head is None or head.next is None or head.next.next is None:
            return head
        n = self.length(head)
        node = head
        for i in range((n+1)/2):
            node = node.next
        stack = []
        for i in range((n+1)/2,n):
            stack.append(node)
            node = node.next
        p = head
        for i in range((n+1)/2,n):
            q = p.next 
            end = stack.pop()
            p.next = end
            end.next = q
            p = q
        if n % 2 == 1:
            p.next = None
        else:
            end.next = None
        return head
    def length(self,head):
        if head is None:
            return 0
        count = 0
        node = head
        while node is not None:
            count += 1
            node = node.next
        return count

  这个方法遍历2.5次链表,第一次求长度,第二次压栈,第三次合并(半趟),可以在oj上pass,但是不满足题目的要求,空间复杂度是O(n/2)。

三、时空上高效的方法

  基于上面用栈的方法,又给我们提供一个思想,那就是要将后面半部分逆转,如果我们能将后半部分逆转,问题就漂亮解决了。Oh,原地逆转链表还不简单,出来了。将后半部分逆转后与前半部分合并即可。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    # @param head, a ListNode
    # @return nothing
    def reorderList(self, head):
        if head is None or head.next is None or head.next.next is None:
            return head
        n = self.length(head)
        node = head
        for i in range((n+1)/2 - 1):
            node = node.next
        new_start = node.next
        node.next = None
        right = self.reverseList(new_start)
        node = head
        while right is not None:
            temp_left = node.next
            node.next = right
            temp_right = right.next
            right.next = temp_left
            node = temp_left
            right = temp_right
        return head
    def reverseList(self,head):
        '''revese the linklist,if it's length is less than 1, return its self'''
        if head is None or head.next is None:
            return head
        q = head
        p = head.next
        head.next = None
        while p is not None:
            temp = p.next
            p.next = q
            q = p
            p = temp
        return q
    def length(self,head):
        if head is None:
            return 0
        count = 0
        node = head
        while node is not None:
            count += 1
            node = node.next
        return count
     

  也只需要扫描2.5篇链表,第一次求长度,第二次逆转后半部分,第三次合并。空间复杂度O(1),时间复杂度O(n)。

posted @ 2014-03-11 14:44  CodeMeals  阅读(365)  评论(0)    收藏  举报
reliable statistics
Visitors