牛客 链表中的节点每k个一组翻转

117 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

描述

将给出的链表中的节点每 k 个一组翻转,返回翻转后的链表
如果链表中的节点数不是 k 的倍数,将最后剩下的节点保持原样
你不能更改节点中的值,只能更改节点本身。

数据范围: \ 0 \le n \le 2000 0≤n≤2000 , 1 \le k \le 20001≤k≤2000 ,链表中每个元素都满足 0 \le val \le 10000≤val≤1000
要求空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)

例如:

给定的链表是 1\to2\to3\to4\to51→2→3→4→5

对于 k = 2k=2 , 你应该返回 2\to 1\to 4\to 3\to 52→1→4→3→5

对于 k = 3k=3 , 你应该返回 3\to2 \to1 \to 4\to 53→2→1→4→5

示例1

输入:

{1,2,3,4,5},2

返回值:

{2,1,4,3,5}

示例2

输入:

{},1

返回值:

{}

算法思想一:栈

解题思路:

利用栈的先进后出规则实现链表的翻转

1、首先遍历链表k个结点入栈,若k大于链表的长度则直接返回链表不翻转

2、栈内结点出栈(翻转)

3、判断剩下的链表个数够不够k个(少于k个不需要反转,大于k个重复 1、2步骤)

4、将已翻转的部分与剩下的链表连接起来

代码

class Solution:
    def reverseKGroup(self , head , k ):
        # write code here
        # 用于链表头元素
        Phead = ListNode(None)
        p = Phead
        while True:
            count = k
            stack = []
            tmp = head
            # 进栈
            while count and tmp:
                stack.append(tmp)
                tmp = tmp.next
                count -= 1
            # 跳出上面循环,tmp是第k+1的元素
            # 如果循环结束,count不为0,则代表不足k个元素
            if count:
                p.next = head
                break
            # 对k个元素进行反转
            # 出栈
            while stack:
                p.next = stack.pop()
                p = p.next
            # 与剩下链表链接起来
            p.next = tmp
            head = tmp
        return Phead.next

算法思想二:递归

解题思路:

1、找到待翻转的k个节点(注意:若剩余数量小于 k 的话,则不需要反转,因此直接返回待翻转部分的头结点即可)。
2、对其进行翻转。并返回翻转后的头结点(注意:翻转为左闭又开区间,所以本作的尾结点其实就是下一作的头结点)。
3、对下一轮 k 个节点也进行翻转操作。
4、将上一轮翻转后的尾结点指向下一轮翻转后的头节点,即将每一轮翻转的k的节点连接起来。

    /**
     * 
     * @param head ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
    public ListNode reverseKGroup (ListNode head, int k) {
        // write code here
        ListNode cur = head;
        int count = 0;
        // 找到待反转的第k个结点
        while (cur != null && count != k) {
            cur = cur.next;
            count++;
        }
        if (count == k) {
            // 递归
            cur = reverseKGroup(cur, k);
            // 反转列表
            while (count != 0) {
                count--;
                ListNode tmp = head.next;
                head.next = cur;
                cur = head;
                head = tmp;
            }
            // 拼接后续的链表
            head = cur;
        }
        return head;
    }
}