题目


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.

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

Note:

  • Only constant extra memory is allowed.
  • You may not alter the values in the list's nodes, only nodes itself may be changed.

思路


先分析题目的几个要求:

  • 每k个节点一组进行翻转,返回翻转之后的链表
  • 如果节点总数不是k的整数倍,则剩余节点保留原有顺序
  • 只能使用常数的额外空间
  • 不能只是单纯改变节点的内部值,而是对节点进行交换

分析可知,题目要求实现两个功能,一个是如何实现每k个节点一组;一个是翻转节点。

  • 每k个节点分组

    • 循环:定义一个变量count记录走过的节点长度。如果count是k的整数倍,就进行翻转;如果不是,继续遍历节点。
    • 递归:分别定义节点1(用于记录每个分组结束位置的下一个节点)和节点2(每个分组的第一个节点),递归将节点2到节点1之间的节点翻转。
  • 翻转节点
    • 头插法
    • 记录节点法

这两个功能所用的方法可以自由组合。

思路1:头插法+递归

分组用递归完成:

定义节点lCur记录分组结束位置的下一个节点,通过k循环来找到每个lCur;利用节点head记录每个分组的开始位置。翻转从headlCur之间的节点,完成一组节点的翻转,得到一组新的节点lHead。此时节点head已经到了分组的最后一位,从后面接上递归调用下一分组得到的新节点lHead,并返回新节点。

翻转用头插法完成(实现方法见Tips):

头插法以链表1->2->3->4->5为例子,假设k=5,完成如下图过程:

思路2:记录节点法+循环

分组用循环完成,翻转用记录节点完成(实现方法见Tips)。

以链表1->2->3->4->5为例子,假设k=4,完成如下过程:

2->1->3->4->5

3->2->1->4->5

4->3->2->1->5

如上是4个一组的节点翻转,每行代表一次循环。

Tips

节点的翻转有两种方法

(1)头插法

新建一个虚拟节点dummy,并保证虚拟节点连接链表的头节点。每当遍历到一个节点时,就把它连接到虚拟节点的下一个节点(整个链表的头部)。定义pCur为当前要翻转的节点,过程如下:

//Step1:新建一个节点记录下一个要翻转的节点
ListNode* pNext = pCur->next;
//Step2:将pCur置于整个节点的头部(即已经翻转好的节点的头部,完成翻转)
pCur->next = dummy->next;
//Step1:更新虚拟节点dummy的指向,使其指向链表的头节点
dummy->next = pCur;
//Step4:更新当前节点,将其置于下一个要翻转的节点
pCur = pNext;

翻转的过程如图所示(以要翻转的节点的值为3为例):

(2)记录节点法

pCur表示当前要翻转的节点,pPre表示当前要翻转的前一个节点(也是已经完成翻转操作的最后一个节点),一次翻转过程(一次循环)如下:

// Step1:pPre连接下一个要翻转的节点
pPre->next = pCur->next;
// Step2:pCur节点连接已经翻转好的节点(翻转当前节点)
pCur->next = dummy->next;
// Step3:更改虚拟节点的连接,使它指向已经翻转好的节点
dummy->next = pCur;
// Step4:pCur指向下一个要翻转的节点
pCur = pPre->next;

翻转的过程如图2所示:

图2:记录节点翻转图解
#C++


  • 思路1
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) { ListNode* lCur =head; //该节点用于记录每组节点结束后的下一个节点 //循环找到每组结束的下一个节点
for(int i= 0 ; i < k; i++){
if(lCur == nullptr)
return head;
lCur = lCur->next;
} ListNode* lHead = reverseOneGroup(head,lCur);
head->next = reverseKGroup(lCur, k);
return lHead;
} /**
* @Description:头插法实现一组节点内的翻转
* lHead:当前一组节点的头节点
* lTail:当前一组节点结束位置的下一个节点
*/
ListNode* reverseOneGroup(ListNode* lHead, ListNode* lTail){
ListNode* dummy = new ListNode(-1);
ListNode* lCur = lHead;
while(lCur != lTail){
ListNode* lNext = lCur->next;
lCur->next = dummy->next;
dummy->next = lCur;
lCur = lNext;
}
return dummy->next;
}
};
  • 思路2
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) { //特殊情况
if(head == nullptr || k ==1)
return head; //辅助的虚拟节点
ListNode* dummy = new ListNode(-1);
//当前节点的上一个节点
ListNode* lPre = dummy;
//当前节点
ListNode* lCur = head; dummy->next = head; int count = 0; //记录长度
while(lCur != nullptr){
count ++;
if(count % k ==0){
lPre = reverseOneGroup(lPre, lCur->next);
lCur = lPre->next;
}
else{
lCur = lCur->next;
}
}
return dummy->next;
} /**
* @Description:记录节点法实现一组节点内的翻转
* lPre:当前一组节点的上一个节点
* lNext:当前一组节点的下一个节点
*/
ListNode* reverseOneGroup(ListNode* lPre, ListNode* lNext){
ListNode* lEnd = lPre->next;
ListNode* lCur = lEnd->next;
while(lCur != lNext){
lEnd->next = lCur->next;
lCur->next = lPre->next;
lPre->next = lCur;
lCur = lEnd->next;
}
return lEnd;
}
};

Python

参考

[1] https://www.cnblogs.com/byrhuangqiang/p/4311336.html

[2] https://www.cnblogs.com/grandyang/p/4441324.html

25. Reverse Nodes in k-Group[H]k个一组翻转链表的更多相关文章

  1. Leetcode 25. Reverse Nodes in k-Group 以每组k个结点进行链表反转(链表)

    Leetcode 25. Reverse Nodes in k-Group 以每组k个结点进行链表反转(链表) 题目描述 已知一个链表,每次对k个节点进行反转,最后返回反转后的链表 测试样例 Inpu ...

  2. 24. Swap Nodes in Pairs(M);25. Reverse Nodes in k-Group(H)

    24. Swap Nodes in Pairs Given a linked list, swap every two adjacent nodes and return its head. For ...

  3. [LintCode] Reverse Nodes in k-Group 每k个一组翻转链表

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

  4. [Leetcode][Python]25: Reverse Nodes in k-Group

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 25: Reverse Nodes in k-Grouphttps://oj. ...

  5. leetcode 25. K 个一组翻转链表

    # coding:utf-8 __author__ = "sn" """ 25. K 个一组翻转链表 给你一个链表,每 k 个节点一组进行翻转,请你返 ...

  6. LeetCode 25. K 个一组翻转链表 | Python

    25. K 个一组翻转链表 题目来源:https://leetcode-cn.com/problems/reverse-nodes-in-k-group 题目 给你一个链表,每 k 个节点一组进行翻转 ...

  7. Java实现 LeetCode 25 K个一组翻转链表

    25. K 个一组翻转链表 给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表. k 是一个正整数,它的值小于或等于链表的长度. 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持 ...

  8. LeetCoded第25题题解--K个一组翻转链表--java--链表

    链表 单链表:链表中的每个元素实际上是一个单独的对象,而所有对象都通过每个元素的引用字段链接在一起. 双链表:与单链表不同的是,双链表的每个节点都含有两个引用字段. 链表优点 灵活分配内存空间 能在O ...

  9. leetcode 24. 两两交换链表中的节点 及 25. K 个一组翻转链表

    24. 两两交换链表中的节点 问题描述 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换. 示例: 给定 1->2-> ...

随机推荐

  1. nslookup 工具的使用方法记录

    查询IP地址 nslookup最简单的用法就是查询域名对应的IP地址,包括A记录和CNAME记录,如果查到的是CNAME记录还会返回别名记录的设置情况.其用法是: nslookup 域名 定查询记录类 ...

  2. 如何在通过脚手架create-react-app 创建的react项目中配置 less

    首先感慨下 自己竟然有半年没登账户 ,干嘛去啦? 从刚接触vue 接手做两次版本之后 又让我这个小菜鸡 开始开发react项目,连react生命周期还没搞明白的时候 就开始进行第一版本的开发了,第一个 ...

  3. BZOJ - 2243 染色 (LCT链修改+链查询)

    同样是可以用LCT解决的树剖问题之一. 注意反转的时候要考虑对左右端点颜色的影响,而且要先反转再打标记(这点不知道为啥) #include<bits/stdc++.h> using nam ...

  4. SpringCloud微服务面试题

    spring data是spring用于简化spring开发中数据访问操作的项目spring Dataspring Data为我们提供了使用统一的API来对数据访问层进行操作,这主要是Spring D ...

  5. 【NOIP2017模拟6.25】小W的动漫

    题目 小W最近迷上了日本动漫,每天都有无数部动漫的更新等着他去看,所以他必须将所有的动漫排个顺序,当然,虽然有无数部动漫,但除了1号动漫,每部动漫都有且仅有一部动漫是它的前传(父亲),也就是说,所有的 ...

  6. 一图解决五大I/O模型比较

  7. CentOS7安装codeblocks

    1.yum -y install epel-release 2.yum clean all && yum makecache 3.yum -y install gtk2-devel c ...

  8. mysql NULL函数 语法

    mysql NULL函数 语法 作用:如果表中的某个列是可选的,那么我们可以在不向该列添加值的情况下插入新记录或更新已有的记录.这意味着该字段将以 NULL 值保存. 说明:NULL 值的处理方式与其 ...

  9. 小程序获取Unionid

    小程序获取用户Unionid,必须授权获取密文.但授权成功后不是永久的.除非关注了公众号或者App微信绑定了, 解决办法是通过code获取openid,然后用openid去数据库查对应的Unionid ...

  10. 更好的构建 Node 服务的工具

    更好的构建 Node 服务的工具 无论前端项目在打包后都发送给后台, 有时候自己想看看效果在运行 npm run build 后只是看到一个 build 文件夹,但是直接打开是无法浏览,因此需要开启一 ...