leetcode oj Reorder List
题目:
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}
要求将链表按如上要求排序,不能修改结点的值,且空间复杂度为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)。