最难链表题——LeetCode题目25:K 个一组翻转链表
时间:2022-07-23
本文章向大家介绍最难链表题——LeetCode题目25:K 个一组翻转链表,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
原题描述
+
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例
给你这个链表:1->2->3->4->5
当 k=2 时,应当返回: 2->1->4->3->5
当 k=3 时,应当返回: 3->2->1->4->5
- 你的算法只能使用常数的额外空间。
- 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
原题链接:https://leetcode-cn.com/problems/reverse-nodes-in-k-group
思路解析
+
这题号称最难链表题,但如果你做过下面这道,那么思路也并不难想。
当k>2时,我们类比来看,依然要记住四个位置。
- K个节点组成的链表中的头节点,类似于上面题目中的first位置;
- K个节点组成的链表中的尾节点,类似于上面题目中的second位置;
- 处于K个节点之后的子链表中,首个节点的位置,类似于上面题目中的head位置;
- 当前操作的K个节点的链表之前的子链表中,其尾部节点的位置,类似于上面题目中prev的位置。
找到上述四个位置之后,我们只需要再将K个节点组成的子链表逆序翻转即可。但这个翻转有坑,因为你要保证在翻转之后,新的头节点和前面的子链表相连,新的尾节点与后面的子链表相连。
复杂度分析
+
- 时间复杂度:
- 空间复杂度:
计算步骤
+
1. 先找到四个重要位置
2. 翻转K个节点的子链表
3. 将翻转后的子链表与外部链表相连
C++参考代码
+
在实现时,我没有使用first,second的命名,而是使用了head和tail表示。此外,每次翻转之后,head指针要后移到未操作部分链表的首部,继续翻转下一个长度为K的子链表。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
pair<ListNode*, ListNode*> reverse(ListNode* head, ListNode* tail) {
ListNode* prev = tail->next, *p = head, *q;
while (prev != tail) {
q = p->next;
p->next = prev;
prev = p;
p = q;
}
return {tail, head};
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode *dummy = new ListNode(-1);
dummy->next = head;
ListNode *tail = dummy, *prev = dummy;
while (prev) {
for (int i = 0; i < k; ++i) {
tail = tail->next;
if (!tail) {
return dummy->next;
}
}
pair<ListNode*, ListNode*> res = reverse(head, tail);
head = res.first;
tail = res.second;
prev->next = head;
head = tail->next;
prev = tail;
}
return dummy->next;
}
};
- 字符串处理技巧
- SwipeRefreshLayout下拉刷新组件
- 使用数字进行字符遍历
- 技术分享:杂谈如何绕过WAF(Web应用防火墙)
- 模拟Executor策略的实现如何控制执行顺序?怎么限制最大同时开启线程的个数?为什么要有一个线程来将结束的线程移除出执行区?转移线程的时候要判断线程是否为空遍历线程的容器会抛出ConcurrentM
- ViewPager快速实现引导页
- Linux学习 - 常用和不太常用的实用awk命令
- 漏洞预警:厄运cookie(Misfortune Cookie)漏洞影响全球1200万台路由器
- 漏洞预警:Google安全研究人员发现NTP(网络时间协议)最新漏洞
- 揭秘:从内部源码看Facebook技术(第一集)
- Python 自然语言处理《釜山行》人物关系
- 注意:C++中double的表示是有误差的
- 完善RecyclerView,添加首尾视图
- 初识Node.js
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 大型前端项目的断点调试共享化和复用化实践
- 常用Linux命令集锦
- 使用Azure Functions玩转Serverless
- Best practice on when to use the wrapper class and primitive type in Java
- Flutter基础widgets教程-BottomNavigationBar篇
- 直播系统介绍
- Azure内容审查器之羞羞图审查
- Clickhouse简介和性能对比
- Clickhouse创建分布式表以及表引擎介绍
- Azure 内容审查器之文本审查
- Redis中String数据类型原理实现
- Clickhouse分布式集群搭建
- Redis过期策略以及淘汰机制
- 几行代码就可以轻松给你的程序加上进度条
- git禁止在master分支push和commit