4-1

25.k个一组翻转链表

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例 :

给定这个链表:1->2->3->4->5

当 k = 2 时,应当返回: 2->1->4->3->5

当 k = 3 时,应当返回: 3->2->1->4->5

说明 :

你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

Python most votes solution:

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

class Solution(object):
    def reverseKGroup(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        dummy = jump = ListNode(0)
        dummy.next = l = r = head

        while True:
            count = 0
            while r and count < k:   # use r to locate the range
                r = r.next
                count += 1
            if count == k:  # if size k satisfied, reverse the inner linked list
                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 dummy.next

分析:

  • 在指针的移动过程中要注意三点:

    第1点:

    等号左边的next表示指向,右边的next表示位置。即:

    a)等号左边若有next,则表示等号左边的指针将指向等号右边的位置。如:

    first.next = second.next
    

    表示first将指向second的下一个位置,如图:

    b)等号左边若无next,则表示等号左边的指针将移动到等号右边的位置。如:

    first = second.next
    

    表示first将移动到second的下一个位置,如图:

    c)等号右边若有next,则表示等号右边指针的后面的位置。如b)中的例子所示。

    d)等号右边若无next,则表示等号右边指针的当前位置。如:

    first = second
    

    表示first将移动到second的位置处。如图:

    第2点:

    代码的写法不同,指针的移法也不同,可以分为“同步”移法和“异步”移法。

    (1)“异步”移法:代码中指针的移动是有先后顺序的。“异步”移动时,每一步的移动都是基于上一步的移动结果进行的,即在前一步的移动结果确定之后,才能进行当前步的移动。这种移法比较好理解,详见第0024题的分析。

    (2)“同步”移法:指针的移动是按“组”完成的,同组内的指针是同时移动的。“同步”移动时,同组内各指针的移动互不干扰,每个指针的移动都只基于这一组指针的初始状态,而与其他指针的状态无关。本例中的代码使用的就是这种移动方法,以下将具体分析本题中各指针的移动过程。

    假设k=3,则在第一个外层while循环的过程中,各指针的移动过程如下图所示(粉红色框表示第一个group,绿色框表示第二个group):

    第二个及以后的while循环中,指针的移动过程均和上面类似。

    算法处理最后几个不够k个一组的元素是通过条件if count == k来判断的。

第3点:

在指针移动的过程中,如果指向某节点的指针始终都没有移动(如指向节点a的指针head),则不管a节点本身如何移动,head指针都会始终指向a节点。在for循环的第三轮结束时,尽管节点a已经发生了很多变动,但jump.next始终都会指向该节点,直到jump指针本身发生变化。

原文地址:https://www.cnblogs.com/tbgatgb/p/11110764.html