25. Reverse Nodes in k-Group[H]k个一组翻转链表
题目
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记录每个分组的开始位置。翻转从head到lCur之间的节点,完成一组节点的翻转,得到一组新的节点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个一组翻转链表的更多相关文章
- Leetcode 25. Reverse Nodes in k-Group 以每组k个结点进行链表反转(链表)
		
Leetcode 25. Reverse Nodes in k-Group 以每组k个结点进行链表反转(链表) 题目描述 已知一个链表,每次对k个节点进行反转,最后返回反转后的链表 测试样例 Inpu ...
 - 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 ...
 - [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 ...
 - [Leetcode][Python]25: Reverse Nodes in k-Group
		
# -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 25: Reverse Nodes in k-Grouphttps://oj. ...
 - leetcode  25. K 个一组翻转链表
		
# coding:utf-8 __author__ = "sn" """ 25. K 个一组翻转链表 给你一个链表,每 k 个节点一组进行翻转,请你返 ...
 - LeetCode 25. K 个一组翻转链表 | Python
		
25. K 个一组翻转链表 题目来源:https://leetcode-cn.com/problems/reverse-nodes-in-k-group 题目 给你一个链表,每 k 个节点一组进行翻转 ...
 - Java实现 LeetCode 25 K个一组翻转链表
		
25. K 个一组翻转链表 给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表. k 是一个正整数,它的值小于或等于链表的长度. 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持 ...
 - LeetCoded第25题题解--K个一组翻转链表--java--链表
		
链表 单链表:链表中的每个元素实际上是一个单独的对象,而所有对象都通过每个元素的引用字段链接在一起. 双链表:与单链表不同的是,双链表的每个节点都含有两个引用字段. 链表优点 灵活分配内存空间 能在O ...
 - leetcode 24. 两两交换链表中的节点 及 25. K 个一组翻转链表
		
24. 两两交换链表中的节点 问题描述 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换. 示例: 给定 1->2-> ...
 
随机推荐
- Codeforces 898 贪心关闭最少闹钟 优先队列最少操作构造N/2squares  讨论情况哈希数字串分割a+b=c
			
A /* Huyyt */ #include <bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define mkp(a,b) ...
 - PHP中替换换行符的几种方法
			
PHP中替换换行的几种方法 参考脚本之家的文章:<PHP中替换换行符的几种方法小结>. 代码: 方法一: $replace_str = str_replace(array("\r ...
 - 调试dcc 试图将u-boot放入ocm运行碰到的问题
			
1. 起因: gd->mon_len = (ulong)&__bss_end - (ulong)_start; 在u-boot.map中查找,发现__bss_end并不是u-boot.b ...
 - 通过telnet自动下载cfg配置文件
			
源代码如下: import telnetlib import logging import datetime import csv import time def telnetfunc(enbid, ...
 - 移动web开发问题和经验总结
			
前言 这里大部分是自己遇到过的情况,还有一部分借鉴了同行的文章,如果大家有遇到其它坑,欢迎提出来一起研究. 知识要点 1. Meta标签 1.禁止用户缩放页面,页面强制让文档的宽度与设备的宽度保持1: ...
 - 【NOIP2016提高A组模拟10.15】打膈膜
			
题目 分析 贪心, 先将怪物按生命值从小到大排序(显然按这个顺序打是最优的) 枚举可以发对少次群体攻击, 首先将所有的群体攻击发出去, 然后一个一个怪物打,当当前怪物生命值大于2,如果还有魔法值就放重 ...
 - Python 元组Ⅰ
			
Python 元组 Python的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号. 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可. 如下实例: 创建空元 ...
 - 一图解决五大I/O模型比较
 - C# 向上取整数
			
PageCount = personInfodb.get_count(selected_id); //数据总数 PageCount = (int)Math.Ceiling(PageCount / (P ...
 - java文件断点续传的简单实现
			
一.概述 所谓断点续传,其实只是指下载,也就是要从文件已经下载的地方开始继续下载.在以前版本的HTTP协议是不支持断点的,HTTP/1.1开始就支持了.一般断点下载时才用到Range和Content- ...