ninehills / blog

https://ninehills.tech
758 stars 68 forks source link

LeetCode-25. Reverse Nodes in k-Group #41

Closed ninehills closed 6 years ago

ninehills commented 7 years ago

问题

https://leetcode.com/problems/reverse-nodes-in-k-group/description/

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

You may not alter the values in the nodes, only nodes itself may be changed.

Only constant memory is allowed.

For example, Given this linked list: 1->2->3->4->5

For k = 2, you should return: 2->1->4->3->5

For k = 3, you should return: 3->2->1->4->5

思路

两种思路都会遍历 n/k*2k = 2n次,时间复杂度都是O(n),但是第二种的空间复杂度是O(k)

  1. 先往后遍历确定是否可以倒序(剩余元素数是否小于k),如果可以,就两两互换
  2. 顺序将k个元素存入数组,然后倒序(应该不符合Only constant memory is allowed.规则)

解答

class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

    def __str__(self):
        return "Node({0}->[{1}])".format(self.val, self.next)

def init_list(l):
    before = None
    for i in l[::-1]:
        n = ListNode(i)
        n.next = before
        before = n
    return n

class Solution(object):
    # from: https://discuss.leetcode.com/topic/31618/succinct-iterative-python-o-n-time-o-1-space
    def reverseKGroup(self, head, k):
        root = jump = ListNode(None)
        root.next = l = r = head
        while True:
            count = 0
            while r and count < k:
                r = r.next
                count += 1
            if count == k:
                pre, cur = r, l
                for _ in range(k):
                    cur.next, cur, pre = pre, cur.next, cur  # standard reversing
                jump.next, jump, l = pre, l, r  # connect two k-groups
            else:
                return root.next

    def reverseKGroup2(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        root = ListNode(None)
        root.next = head
        head = root
        while True:
            p = head
            tmp = []
            for i in range(k):
                if p.next == None:
                    return root.next
                tmp.append(p.next)
                p = p.next
            for i in range(k):
                if i == 0:
                    tmp[i].next = p.next
                else:
                    tmp[i].next = tmp[i-1]
            head.next = tmp[i]
            head = tmp[0]
        return root.next

print Solution().reverseKGroup(init_list([1,2,3,4,5]), 2)
print Solution().reverseKGroup(init_list([1,2,3,4,5]), 3)
ninehills commented 7 years ago

4 20170802