K个一组翻转链表

题目描述

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

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

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

来源:力扣(LeetCode)
链接:k个一组翻转链表

测试样例分类

1.总结点个数不满k

2.总结点个数恰好为k的正整数倍

3.总结点个数为k的正整数倍加上remain(0<remain<k)

解题思路

按照测试样例的分类,可以对int型链表长度用/运算符得到有多少组。

  • 对情况一:结果为0,无需翻转,直接返回头结点即可。
  • 对情况二和三:结果为正整数,将每k个作为一组进行翻转,最后余下的不足k个的那一组直接取其头结点连接至最后的尾结点。

需要注意的点

在迭代法方式中,需要注意当前处理的组的头结点指针和尾结点指针,以及下一个组的头结点指针。

在递归方式中,需要将当前处理的组的头指针、当前组序号、总组数、k值作为参数传递。返回的是处理好的当前组的头结点指针。

代码&图解

状态图

srpuPH.md.jpg

迭代方式

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        //先求得链表的长度
        int cnt = 0;
        ListNode *cur = head;
        while(cur){
            ++cnt;
            cur = cur->next;
        }
        //若不足k个结点
        if(cnt / k == 0){
            return head;
        }
        //记录有多少组k个结点
        int group = 0;
        ListNode *dummy = new ListNode();
        ListNode *rear = dummy;
        cur = head;
        while(group < cnt / k){
            ListNode *new_rear = cur;
            for(int i = 0;i < k;++i){
                ListNode *cur_next = cur->next;
                cur->next = rear->next;
                rear->next = cur;
                cur = cur_next; 
            }
            rear = new_rear;
            ++group;
        }
        rear->next = cur;
        return dummy->next;
    }
};

递归方式

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
       //遇到k个一组的最后一个结点时,则递归处理,处理内容为对接下来的k各结点翻转
       //先求链表长度
       int cnt = 0;
       ListNode *cur = head;
       while(cur){
           ++cnt;
           cur = cur->next;
       } 
       return reverseK(head,cnt/k,0,k);
    }

    //传入k个一组的首结点,k组的总组数,当前是第几组
    //返回一个翻转好的k个一组的首结点
    ListNode *reverseK(ListNode* head,int group_cnt,int group_cur,int k){
        if(group_cur == group_cnt){
            return head;
        }
        ListNode *rear = head;
        ListNode *pre = NULL;
        ListNode *cur = head;
        for(int i = 0;i < k;++i){
            ListNode *cur_next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = cur_next;
        }
        rear->next = reverseK(cur,group_cnt,group_cur+1,k);
        return pre;
    }
};

复杂度分析

时间复杂度:两种方式都为O(n)

空间复杂度:迭代方式为O(1),递归方式递归深度为(n/k)向下取整,故其空间复杂度为O(n/k)

欢迎大家转载本人的博客(需注明出处),本人另外还有一个个人博客网站:[https://www.lularible.cn],欢迎前去浏览。

posted @ 2021-01-17 21:23  lularible  阅读(117)  评论(0编辑  收藏  举报