leetcode 25. Reverse Nodes in k-Group Python3 递归+迭代

一.问题描述

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.

Follow up:

  • Could you solve the problem in O(1) extra memory space?
  • You may not alter the values in the list's nodes, only nodes itself may be changed.

 

Example 1:

Input: head = [1,2,3,4,5], k = 2
Output: [2,1,4,3,5]

Example 2:

Input: head = [1,2,3,4,5], k = 3
Output: [3,2,1,4,5]

Example 3:

Input: head = [1,2,3,4,5], k = 1
Output: [1,2,3,4,5]

Example 4:

Input: head = [1], k = 1
Output: [1]

二.解题思路

题目的意思就是说一个长为n的链表,每k个一组,在这组内翻转链表,组合组之间的顺序还是要保持一直,如果链表长度不能整除k,那么剩余的链表顺序应该保持一致。

解决的思路也比较直观,可以开个数组,把一组子链表按顺序存储下来。对于每个子链表进行翻转,记录好头和尾,之后迭代到下一个子链表,翻转完后,让上一个子链表的尾指向现在子链表的头,重复直到数组处理完毕。

要注意一下最后一个子链表,如何长度小于k应该保持不变,不过这个应该在将链表存储为子链表数组的时候就应该标记好的,不用做特别的处理。

时间复杂度:O(N),空间复杂度:O(N/k).

比较有趣的是题目的follow-up,期待我们用O(1)空间和不改变链表节点的value,只改变它本身来解决这个问题,这也是面试的时候考官很容易问的follow-up,

解决思路也很简单,和上面类似,不过我们不把原来链表分割成子链表组,直接迭代处理链表,对遇到的链表,我们进行翻转,这时候就需要一个指针来记录迭代的链表的次数,达到k之后,说明我们已经翻转好了一个子链表。

下一步要做的就是,要把这个子链表和上个子链表相连接,即让上一个子链表的尾指向当前子链表的头,因为我们没有用一个数组来保存子链表,因此需要开变量来记录上个子链表的尾。

然后就是对于不足k的子链表的处理,我的做法是遇到的就翻转,如果发现子链表迭代完但是还不到k次,那就把当前链表再翻转一次,实现保持原样。

当然每一个子链表的连接除了迭代,也可以用递归实现。

递归:

递归的话重点的话就是确定递推式,即确定函数的返回变量以及结束条件。其实也很明显,我们从前往后递归,让递归函数返回当前子链表的头,然后让当前递归的子链表的尾指向子递归返回的头即可。

递归结束条件为当前处理的链表为None,说明链表处理完毕。

其实和迭代大同小异。

时间复杂度:O(N),空间复杂度:O(1).

三.源码

# O(N) Time and O(1) memory, 迭代

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        def reverseNode(ln,k):
            i=0
            tail=ln
            pre=None
            cur=ln
            while i<k:
                if not cur:
                    return reverseNode(pre,i)
                ln=ln.next
                cur.next=pre
                pre=cur   
                cur=ln 
                i+=1
            tail.next=None
            return pre,tail,cur
        
        if not head:return None
        new_head=ListNode()
        pre_tail=new_head
        while head:
            cur_head,cur_tail,head=reverseNode(head,k)
            pre_tail.next=cur_head
            pre_tail=cur_tail
        return new_head.next

# O(N) Time and O(1) memory, 递归
class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        def reverseNode(ln,k):
            i,tail,pre,cur=0,ln,None,ln
            while i<k:
                if not cur:
                    return reverseNode(pre,i)
                ln=ln.next
                cur.next=pre
                pre=cur   
                cur=ln 
                i+=1
            tail.next=None
            return pre,tail,cur
        
        if not head:return None
        cur_head,cur_tail,head=reverseNode(head,k)
        cur_tail.next=self.reverseKGroup(head,k)
        return cur_head

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值