算法通关村第二关——指定区间反转问题
指定区间反转:
Leetcode92有这样一道题:给你单链表的头指针head和两个整数left、right,其中left<=right,请你反转从位置left到位置right的链表结点,返回反转后的链表,如图所示:
这道题呢,有两种不同的解法,分别是头插法和穿针引线法,头插法就是我们前面说过的带头结点的反转,而穿针引线法就是不带头结点实现反转的方法,接下来我将逐一介绍:
1.头插法:
前面我们说过带头结点的反转有两个重点要求:1.虚拟头结点 2.拆拆拆
熟练掌握以上两个思想后,这道题的解决将变得十分简单。在这道题中,我认为我们可以将区间前的第一个结点看作虚拟头结点,而区间内除第一个结点以外的全部结点则需要逐一拆除并进行插入,如下图所示:
我们可以建立一个cur指针始终指向区间的第一个元素,之后的每一步操作我们需要以下几个步骤:1.找到当前结点的下一个结点 2.拆除:令cur指针指向的结点指向next结点的下一个结点(即:将next指针指向的结点“拆下”,并保存后一个结点的位置)3.插入: 令next指针指向的结点指向虚拟头结点的下一个结点(这里的虚拟头结点就是我们说的区间前的第一个结点) 4:令虚拟头结点指向next指针所指向的结点。重复上述操作,即可实现区间反转,代码如下:
-
// 头插法
-
struct ListNode* reverseBetween(struct ListNode* head, int left, int right)
-
{
-
struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));//开辟一个虚拟的头结点
-
dummy->val = -1;
-
dummy->next = head;//令虚拟头结点的下一个结点指向真实头结点
-
struct ListNode* ans = dummy;//创建一个指针用来遍历链表
-
for (int i = 0; i < left - 1; i )
-
{
-
ans = ans->next; //找到指定区间的前一个元素
-
}
-
struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
-
cur = ans->next;//令cur为区间的第一个结点,并始终保持不变
-
for (int i = 0; i < right - left; i )//遍历整个区间
-
{
-
struct ListNode* next = cur->next;//首先找到当前结点的下一个结点
-
cur->next = next->next;//令当前结点的下一个结点指向下一个结点所指向的结点,即将next结点“拆下”
-
next->next = ans->next;//令next结点的下一个结点指向区间前的结点所指向的结点
-
ans->next = next;//令区间前的结点指向next结点
-
}
-
return dummy->next;
-
}
2.穿针引线法:
如果说第一种方法的特点是拆拆拆,那这一种方法的特点就类似于从整体上解决问题的方法,让我们先从图片中了解大致思想:
这种方法呢,其实就是将整个区间先与原链表脱离,单独将区间反转之后再接入原链表,步骤如下:1.找到区间的前驱结点与后续结点,便于之后进行连接 2.定位区间的左结点与右结点 3.将整个区间拆下 4.对区间进行反转 5.将反转后的区间接入旧链表,代码如下:
-
//反转链表
-
void reverseList(strruct ListNode* head)
-
{
-
sturct ListNode* pre = NULL;
-
struct ListNode* cur = head;
-
while (cur != NULL)
-
{
-
struct ListNode* next = cur->next;
-
cur->next = pre;
-
pre = cur;
-
cur = next;
-
}
-
-
}
-
//穿针引线法
-
struct ListNode* reverseBetween(struct ListNode* head, int left, int right)
-
{
-
struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
-
dummy->val = -1;
-
dummy->next = head;
-
struct ListNode* pre = dummy;
-
for (int i = 0; i < left - 1; i )
-
{
-
pre = pre->next;//首先找到区间的前一个结点
-
}
-
struct ListNode* rightNode = pre;
-
for (int i = 0; i < right - left 1; i )
-
{
-
rightNode = rightNode->next;//令该结点指向区间的最后一个结点
-
}
-
struct ListNode* leftNode = pre->next;//找到区间的第一个结点
-
struct ListNode* succ = rithtNode->next;//找到区间之后的第一个结点
-
rightNode->next = NULL;
-
pre->next = NULL;//断开区间链表与原链表的链接
-
reverseList(leftNode);//将区间内的链表进行反转
-
pre->next = rightNode;//令之前保存的区间前的第一个结点指向此时链表的头结点
-
leftNode->next = succ;//令链表的尾结点指向之前保存的区间之后的第一个结点
-
return dummy->next;
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgekbeh
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01