【LeetCode题解】25_k个一组翻转链表(Reverse-Nodes-in-k-Group)
更多 LeetCode 题解笔记可以访问我的 github。
描述
给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明 :
- 你的算法只能使用常数的额外空间。
- 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
解法一:迭代
思路
要求解这道题,先要构造一个辅助函数,这个函数的作用就是翻转链表(不包括首尾节点)。假设输入链表如下图所示,其中链表表头为 begin,链表尾部为 end。

经过函数之后,链表的连接变为如下的形式,且将 begin 作为函数的输出。

具体的实现思路和 LeetCode 第206题翻转链表是一致的,只是函数的输入和输出有些不同,这里不在赘言,直接给出函数的实现。
// Java 版本
private ListNode reverse(ListNode begin, ListNode end) {
ListNode prev = begin, curr = begin.next;
ListNode first = curr;
while (curr != end) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
begin.next = prev;
first.next = curr;
return first;
}
# Python 版本
def reverse(begin, end):
prev, curr, first = begin, begin.next, begin.next
while curr != end:
curr.next, prev, curr = prev, curr, curr.next
begin.next, first.next = prev, curr
return first
有个上面的辅助函数之后,我们就可以利用它求解这道题。假设输入链表为 1 -> 2 -> 3 -> 4 -> 5 且 k=3,首先构造一个虚拟头节点 dummy,用于统一后面的一系列操作。初始时,设变量 i=0,当 i+1 不能被3整除时,将 head 指针向链表的下一个节点移动;当 i+1 能被3整除时,调用上面的辅助函数,将 begin 节点和 head.next 节点之间的节点进行翻转。具体的操作可以看下面的图片演示。




之后,将 head 指针指向 begin 指针的下一个节点(这里为 4),即 head = begin.next。如此循环往复,直到 head 节点为 null,则结束所有操作。
Java 实现
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
// boundary judgement
boolean hasNoOrOneNode = (head == null || head.next == null);
if (hasNoOrOneNode || k == 1) {
return head;
}
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode begin = dummy;
int i = 0;
while (head != null) {
++i;
if (i % k == 0) {
begin = reverse(begin, head.next);
head = begin.next;
} else {
head = head.next;
}
}
return dummy.next;
}
private ListNode reverse(ListNode begin, ListNode end) {
ListNode prev = begin, curr = begin.next;
ListNode first = curr;
while (curr != end) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
begin.next = prev;
first.next = curr;
return first;
}
}
// Runtime: 3 ms
// Your runtime beats 100.00 % of java submissions.
Python 实现
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
has_no_or_one_node = (not head or not head.next)
if has_no_or_one_node or k == 1:
return head
dummy = ListNode(-1)
dummy.next = head
begin = dummy
i = 0
while head:
i += 1
if i % k == 0:
begin = self._reverse(begin, head.next)
head = begin.next
else:
head = head.next
return dummy.next
def _reverse(self, begin, end):
prev, curr, first = begin, begin.next, begin.next
while curr != end:
curr.next, prev, curr = prev, curr, curr.next
begin.next, first.next = prev, curr
return first
复杂度分析
- 时间复杂度:\(O(n)\)
- 空间复杂度:\(O(1)\)
解法二:递归(不满足空间复杂度)
思路
递归的思路和迭代的思路是一样的,也是对 k 个为一组的节点进行翻转,区别在于递归是按照从后往前的顺序分别对每组节点进行翻转,而迭代则是从前往后。
Java 实现
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode curr = head;
int i = 0;
while (curr != null && i < k) {
++i;
curr = curr.next;
}
if (i == k) {
curr = reverseKGroup(curr, k);
while (i > 0) {
ListNode tmp = head.next;
head.next = curr;
curr = head;
head = tmp;
--i;
}
head = curr;
}
return head;
}
}
Python 实现
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
curr = head
i = 0
while curr and i < k:
curr = curr.next
i += 1
if i == k:
curr = self.reverseKGroup(curr, k)
while i > 0:
head.next, head, curr = curr, head.next, head
i -= 1
head = curr
return head
复杂度分析
- 时间复杂度:\(O(n)\)
- 空间复杂度:\(O(n)\)
【LeetCode题解】25_k个一组翻转链表(Reverse-Nodes-in-k-Group)的更多相关文章
- [Swift]LeetCode25. k个一组翻转链表 | Reverse Nodes in k-Group
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. k ...
- [Leetcode] 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 ...
- Reverse Nodes In K Group,将链表每k个元素为一组进行反转---特例Swap Nodes in Pairs,成对儿反转
问题描述:1->2->3->4,假设k=2进行反转,得到2->1->4->3:k=3进行反转,得到3->2->1->4 算法思想:基本操作就是链表 ...
- K组翻转链表 · Reverse Nodes in k-Group
[抄题]: 给你一个链表以及一个k,将这个链表从头指针开始每k个翻转一下.链表元素个数不是k的倍数,最后剩余的不用翻转. [思维问题]: [一句话思路]: // reverse head->n1 ...
- [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 ...
- Java实现 LeetCode 25 K个一组翻转链表
25. K 个一组翻转链表 给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表. k 是一个正整数,它的值小于或等于链表的长度. 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持 ...
- LeetCoded第25题题解--K个一组翻转链表--java--链表
链表 单链表:链表中的每个元素实际上是一个单独的对象,而所有对象都通过每个元素的引用字段链接在一起. 双链表:与单链表不同的是,双链表的每个节点都含有两个引用字段. 链表优点 灵活分配内存空间 能在O ...
- 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 个节点一组进行翻转 ...
随机推荐
- hdu 5073 有坑+方差贪心
http://acm.hdu.edu.cn/showproblem.php?pid=5073 就是给你 n 个数,代表n个星球的位置,每一个星球的重量都为 1 开始的时候每一个星球都绕着质心转动,那么 ...
- Brain Rules: 12 Principles for Surviving and Thriving at Work, Home, and School
选自 https://litemind.com/brain-rules/
- E - Tears of Drowned
Description Tia Dalma: Come. What service may I do you? You know I demand payment. Jack: I brought p ...
- PCA in MLLib
SVD分解: \(A=U\Sigma V^T\),变换:\(\hat{A}=A\cdot V=U\Sigma\) 分解时先计算\(A^TA=U\Sigma^2U^T\),再进行SVD分解 /** * ...
- vue项目webpack中Npm传递参数配置不同域名接口
项目开发中,前端在配置后端api域名时很困扰,常常出现:本地开发环境: api-dev.demo.com测试环境: api-test.demo.com线上生产环境: api.demo.com, 这次是 ...
- node.js global object,util and so on
核心模块主要内容: 全局对象 常用工具 事件机制 文件系统访问 http服务器和客户端 global object: 所有的全局变量(除了global本身外)都是global object 的属性(a ...
- C# 不能用于文件名的字符
在 Windows 有一些字符是不能作为文件名,尝试重命名一个文件,输入/ 就可以看到windows 提示的不能作为文件名的字符 那么具体是包括哪些符号不能作为文件名? Tilde (~) Numbe ...
- ServiceStack 错误处理
抛出C#异常 在大多数情况下,您不需要关心ServiceStack的错误处理,因为它为抛出C#异常的正常用例提供本机支持,例如: public object Post(User request) { ...
- UWP 大爆炸你个锤子
今天看到 叫我蓝火火 s的 UWP中实现大爆炸效果(一) ,我也来说一下我的app [小薇自然语言处理]实现的大爆炸技术. 看一下效果先. 我的控件是基于wrappanel的,正如蓝火火说的,这样看 ...
- css伪元素:before和:after用法详解
css的伪元素,之所以被称为伪元素,是因为他们不是真正的页面元素,html没有对应的元素,但是其所有用法和表现行为与真正的页面元素一样,可以对其使用诸如页面元素一样的css样式,表面上看上去貌似是页面 ...