Description: Given a singly linked list L: L0→L1→…→Ln-1→Ln, reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You may not modify the values in the list's nodes, only nodes itself may be changed.
Link: https://leetcode.com/problems/reorder-list/
Examples:
Example 1: Given 1->2->3->4, reorder it to 1->4->2->3. Example 2: Given 1->2->3->4->5, reorder it to 1->5->2->4->3.
思路: 最直接的做法就是每次将链表分成两部分,reordered part and the part to reorder, 已经重新排序过的部分和待排序的部分,记录 the tail of reordered part is pointer p and the head of the part to reorder is q. 每次 1) 找到待排序链表的结尾,将尾节点的前一个node记为pre,pre.next = None; 2) 将尾节点连接到p, 将p.next连接到尾节点; 3) update p and q. 直到p.next = None (即没有待排序的部分),或者q.next = None (待排序的部分只有一个点)。
class Solution(object): def reorderList(self, head): """ :type head: ListNode :rtype: None Do not return anything, modify head in-place instead. """ if head and head.next and head.next.next: p = head q = p.next while p.next and q.next: # print(p.val) while q.next: pre = q q = q.next pre.next = None s = p.next p.next = q q.next = s p = s q = p.next
但这样会超时的,因为每次都要找待排序的尾节点。为了不要每次查找,就需要存储。第一次遍历时,记录所有的节点并计算总长度length, 再次遍历时是需要遍历总链表长度的一半,步骤和上面是一样的,只是待排序的尾节点不需要遍历到结尾才能找到,而是直接在nodes list中根据位置 i 找到。这样时间和空间都很好。
class Solution(object): def reorderList(self, head): """ :type head: ListNode :rtype: None Do not return anything, modify head in-place instead. """ p = head length = 0 nodes = list() while p: nodes.append(p) length += 1 p = p.next if length % 2 == 0: N = int(length/2) else: N = int(length/2) + 1 # print(length, N) i = 0 while i < N-1: p = nodes[i] # update p q = nodes[length-i-1] # find tail of q nodes[length-i-2].next = None # pre.next = None s = p.next p.next = q q.next = s i += 1
日期: 2020-11-27 快周末了呢, 激动的心!