力扣25(java&python)-K 个一组翻转链表(困难)
题目:
给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例1:
输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]
示例2:
输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]
提示:
- 链表中的节点数目为
n
1 <= k <= n <= 5000
0 <= Node.val <= 1000
进阶:你可以设计一个只用 O(1)
额外内存空间的算法解决此问题吗?
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/reverse-nodes-in-k-group
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
一、模拟
参考 @康建斌学算法 大佬的解题思路,同时感谢评论区的各位提的疑问以及注解~
1.设置虚拟头结点,指向原始头结点将头结点当做普通结点来对待,减少特殊判断,将链表分区为已翻转部分+待翻转部分+未翻转部分;
2.定义两个指针,pre:每次要翻转链表头结点的前一个结点,end:待翻转链表的尾结点,让其初始都指向虚拟结点;
3.对链表进行遍历,首先通过给定的k来循环,找到第一次需要翻转的链表的范围;
4.经过k次循环后,end到达本次待翻转链表的尾结点,需要保存尾结点的下一个结点:ListNode next = end.next,找到待翻转链表的开始结点: ListNode start = pre.next,并断开end与next的连接:end.next = null;
5.对[start,end]区间的结点进行翻转,将这个待翻转的子链表进行操作:
- 定义三个指针,preNode:前一个结点指针,currNode:当前结点指针,nextNode:下一个结点指针;
- 然后对待翻转的结点进行循环,循环结束的条件是:当 当前结点为空:
- 先保存当前结点后面链表: nextNode = currNode.next;
- 将当前结点指向preNode: currNode.next = preNode;
- 更新preNoded位置,preNode向后移动指向当前结点:preNode = currNode;更新curNode位置,curNode向后移动,下一个结点变成当前结点:currNode = nextNode;
- 最后实现全部翻转,currNode为空,返回这时的preNode
5.将pre.next指向翻转后的链表:pre.next = reverse(start);并将已翻转的部分和待翻转的部分连接,尾结点指向它的下一个结点:

6.一直重复上述步骤,直到end为null时,结束遍历,最终返回 dummyHead.next。
java代码:
1 /**
2 * Definition for singly-linked list.
3 * public class ListNode {
4 * int val;
5 * ListNode next;
6 * ListNode() {}
7 * ListNode(int val) { this.val = val; }
8 * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 * }
10 */
11 class Solution {
12 public ListNode reverseKGroup(ListNode head, int k) {
13 //定义一个虚拟结点并指向头结点
14 ListNode dummyHead = new ListNode(0,head);
15 //定义两个指针初始都指向虚拟结点
16 //pre:每次要翻转链表头结点的前一个结点
17 //end:要翻转链表的尾结点
18 ListNode pre = dummyHead;
19 ListNode end = dummyHead;
20 //当到达尾结点的时候退出while循环
21 //找到end的位置
22 while(end.next != null){
23 //end != null:防止end.next为空报错
24 for(int i = 0; i < k && end != null; i++){
25 end = end.next;
26 }
27 //当不足k倍时,直接退出不进行翻转
28 if(end == null) break;
29
30 //翻转的开始结点
31 ListNode start = pre.next;
32 //保存end的下一个结点
33 ListNode next = end.next;
34 //断开end和下一个结点的连接
35 end.next = null;
36 //将pre.next指向翻转后的链表
37 pre.next = reverse(start);
38 //将尾结点指向end的下一个结点
39 start.next = next;
40 //将pre换成下一次翻转链表头结点的前一个结点
41 pre = start;
42 //将end也要换成下一次翻转链表头结点的前一个结点
43 end = start;
44 }
45 //最后返回虚拟头结点的下一个结点=真正的头结点
46 return dummyHead.next;
47 }
48 public ListNode reverse(ListNode head){
49 //当子链表为空或者只有单结点时,直接返回原表
50 if(head == null || head.next == null) return head;
51 //定义三个指针
52 //preNode前一个结点指针
53 //currNode当前结点指针
54 //nextNode下一个结点指针
55 ListNode preNode = null;
56 ListNode currNode = head;
57 ListNode nextNode = null;
58 //循环结束条件是当当前结点为空
59 while(currNode != null){
60 //先保存下一个结点
61 nextNode = currNode.next;
62 //当前结点指向preNode
63 currNode.next = preNode;
64 //更新preNoded位置
65 preNode = currNode;
66 //更新curNode位置
67 currNode = nextNode;
68 }
69 return preNode;
70 }
71 }
python3代码:
1 # Definition for singly-linked list.
2 # class ListNode:
3 # def __init__(self, val=0, next=None):
4 # self.val = val
5 # self.next = next
6 class Solution:
7 def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
8 dummyHead = ListNode(0,head)
9 pre, end = dummyHead, dummyHead
10 while end.next:
11 # 确定end的位置
12 i = 0
13 while i < k and end:
14 end = end.next
15 i += 1
16 # end为空
17 if not end:
18 break
19 # start的位置
20 start = pre.next
21 # 保存end的下一个结点并断开连接
22 next = end.next
23 end.next = None
24
25 # 将pre连接已翻转的链表
26 pre.next = self.reverse(start)
27
28 # 将start连接下一个待翻转的链表
29 start.next = next
30 # 更新pre和end的位置,在下一个翻转链表头结点的前一个结点
31 pre = start
32 end = start
33 return dummyHead.next
34
35 def reverse(self, head):
36 # 特殊判断
37 if not head or not head.next:
38 return head
39 cur = head
40 pre = None
41 next = None
42 while cur:
43 # 保存cur下一个结点
44 next = cur.next
45 # 将cur指向pre
46 cur.next = pre
47 # 将pre移动到cur,将cur移动到next
48 pre = cur
49 cur = next
50 return pre

2.找到待翻转的k个结点,如果剩余结点的数量小于k,则不需要翻转,直接返回剩下部分的头结点就行;
3.对[head,end)区间的结点进行翻转(翻转的结点不包括end),并返回翻转后的头结点newHead;
4.再以同样的方式,对剩下的结点进行翻转:head.next = reverseKGroup(end, k);
java代码:
1 /**
2 * Definition for singly-linked list.
3 * public class ListNode {
4 * int val;
5 * ListNode next;
6 * ListNode() {}
7 * ListNode(int val) { this.val = val; }
8 * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 * }
10 */
11 class Solution {
12 public ListNode reverseKGroup(ListNode head, int k) {
13 //特殊判断
14 if(head == null || head.next == null) return head;
15 //设定一个end指针
16 ListNode end = head;
17 for(int i = 0; i < k; i++){
18 //如果剩下的结点不足k个
19 if(end == null) return head;
20 end = end.next;
21 }
22 //翻转前k个元素
23 ListNode newHead = reverse(head, end);
24 //下一轮翻转从end开始
25 head.next = reverseKGroup(end, k);
26
27 return newHead;
28 }
29 public ListNode reverse(ListNode head, ListNode end){
30 //定义两个指针
31 //preNode前一个结点指针
32 //nextNode下一个结点指针
33 ListNode preNode = null;
34 ListNode nextNode = null;
35 //循环结束条件是当head没有到尾结点时
36 while(head != end){
37 //先保存下一个结点
38 nextNode = head.next;
39 //当前结点指向preNode
40 head.next = preNode;
41 //更新preNoded位置
42 preNode = head;
43 //更新head位置
44 head = nextNode;
45 }
46 return preNode;
47 }
48 }
python3代码:
1 # Definition for singly-linked list.
2 # class ListNode:
3 # def __init__(self, val=0, next=None):
4 # self.val = val
5 # self.next = next
6 class Solution:
7 def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
8 # 特殊判断
9 if not head or not head.next:
10 return head
11 end = head
12
13 for i in range(k):
14 # not end:end为空,不足k个
15 if not end:
16 return head
17 end = end.next
18
19 # 翻转链表
20 newHead = self.reverse(head, end)
21 # 递归翻转剩下的
22 head.next = self.reverseKGroup(end, k)
23
24 return newHead
25
26 def reverse(self, head, end):
27 pre = None
28 next = None
29 while head != end:
30 # 保存head下一个结点
31 next = head.next
32 # 将head指向pre
33 head.next = pre
34 # 将pre移动到head,将head移动到next
35 pre = head
36 head = next
37 return pre
力扣25(java&python)-K 个一组翻转链表(困难)的更多相关文章
- LeetCoded第25题题解--K个一组翻转链表--java--链表
链表 单链表:链表中的每个元素实际上是一个单独的对象,而所有对象都通过每个元素的引用字段链接在一起. 双链表:与单链表不同的是,双链表的每个节点都含有两个引用字段. 链表优点 灵活分配内存空间 能在O ...
- Java实现 LeetCode 25 K个一组翻转链表
25. K 个一组翻转链表 给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表. k 是一个正整数,它的值小于或等于链表的长度. 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持 ...
- LeetCode 25. K 个一组翻转链表 | Python
25. K 个一组翻转链表 题目来源:https://leetcode-cn.com/problems/reverse-nodes-in-k-group 题目 给你一个链表,每 k 个节点一组进行翻转 ...
- leetcode 25. K 个一组翻转链表
# coding:utf-8 __author__ = "sn" """ 25. K 个一组翻转链表 给你一个链表,每 k 个节点一组进行翻转,请你返 ...
- leetcode 24. 两两交换链表中的节点 及 25. K 个一组翻转链表
24. 两两交换链表中的节点 问题描述 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换. 示例: 给定 1->2-> ...
- [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 ...
- k个一组翻转链表(java实现)
题目: 给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表. k 是一个正整数,它的值小于或等于链表的长度.如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序. 示例 : 给定这 ...
- [LeetCode]25. 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. k ...
- js 之k个一组翻转链表
题目描述 将给出的链表中的节点每\ k k 个一组翻转,返回翻转后的链表如果链表中的节点数不是\ k k 的倍数,将最后剩下的节点保持原样你不能更改节点中的值,只能更改节点本身.要求空间复杂度 \ O ...
- 力扣——Reverse Nodes in k-Group(K 个一组翻转链表) python实现
题目描述: 中文: 给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表. k 是一个正整数,它的值小于或等于链表的长度. 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序 ...
随机推荐
- Vue 动态插入组件 用js函数的方式
Vue 动态插入组件 用js函数的方式 第一步 import vue组件 第二步 Vue把组件扩展进去 第三步 创建实例 第四步 将组件的el挂载到document.body上 第五步 设置组件内部d ...
- C++串口通讯解决方案
这篇文章只是笔记性质,没有实际的原创内容,主要是做一下方案的备份. 串口通讯使用开源的 CSerialPort 类,我使用的是Windows版本分支: CSerialPort 跨平台 CSerialP ...
- 什么是docker的多阶段构建
Docker多阶段构建是一种技术,允许在不同的构建阶段中使用不同的基础镜像,并只复制构建所需的文件和依赖项.这种技术旨在减少最终生成的Docker镜像的大小和运行时的资源消耗. 多阶段构建的一般工作流 ...
- [STM32]STM32双机串口通信
[STM32]STM32双机串口通信 上一篇的通信方案在发送端高强度通信下寄了,发现是函数HAL_UART_Transmit()的锅,一个函数居然能跑0.3s左右...于是打算选用DMA收发数据,但是 ...
- CodeForces Hello 2024 个人题解(A~C)
A. Wallet Exchange 时间限制: 1秒 内存限制: 256兆 输入: 标准输入 输出: 标准输出 Alice and Bob are bored, so they decide to ...
- 在 Windows 上利用Qwen大模型搭建一个 ChatGPT 式的问答小助手
本文首发于公众号:Hunter后端 原文链接:在 Windows 上利用Qwen大模型搭建一个 ChatGPT 式的问答小助手 最近 ChatGPT 式的聊天机器人比较火,可以提供各种问答功能,阿里最 ...
- Flutter Utils 全网最齐全的工具类
FlutterUtils 目录介绍 01.事件通知bus工具类 02.颜色Color工具类 03.日期转化工具类 04.File文件工具类 05.Sql数据库工具类 06.Json转化工具类 07.L ...
- 记录--for in 和 for of的区别详解以及为for in的输出顺序
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 for in 和 for of 相对于大家肯定都不陌生,都是用来遍历属性的没错.那么先看下面的一个例子: 例1 const obj = { ...
- vue初学核心基础02
8.v-bind补充 8.1v-bind绑定类名 v-bind指令给"任意标签"的"任意属性"绑定数据 对于大部分的属性而言我们只需要直接赋值即可, 例如:va ...
- 索引与查询使用的 collate 不一致导致无法使用索引
索引与表的collate 不一致的情况下,会导致表上的索引不可用,这时要想使用索引,必须在SQL 语句指定建索引所用的collate. 数据库默认collate : test=# \l List of ...