大家好,我是怒码少年小码。
新的一天,新的考验。今天是反转链表的一个拓展,说真的有点意思~
LeetCode92:给单链表的头指针head和两个整数left和right,其中left <= right。反转left位置到right位置的链表结点,返回反转后的链表。
示例:
- 输入:head=[9,7,2,5,4,3,6],left=3,right=6
- 输出:[9,7,3,4,5,2,6]
什么是头插法可以看我前面的文章:反转链表的两种方法
主要思想是在需要反转的区间里遍历所有结点,让所有结点插到反转部分的起始位置:
直接上代码:
LinkNode* reverseBetween(LinkNode* head, int left,int right){
LinkNode* dummyNode = new LinkNode;
dummyNode->next = head;
LinkNode* pre = dummyNode;
//找到反转区间头的前一个结点
for (int i = 0; i < left - 1; i++) {
pre = pre->next;
}
//指向要反转的第一个结点
LinkNode* cur = pre->next;
LinkNode* next;
for (int i = 0; i < right - left; i++) {
//保存下一个要反转的结点
next = cur->next;
//cur结点练到下一个结点的后一个结点,
cur->next = next->next;
//next结点接到pre后
next->next = pre->next;
//pre后连接next
pre->next = next;
//cur结点换到原来的后一个结点,原来的后一个结点跳到pre后面
}
LinkNode* newHead = dummyNode->next;
free(dummyNode);
return newHead;
}
pre
指向虚拟链表反转区间的前一个结点,所以需要从虚拟结点开始,这样哪怕left = 1
从第一个结点开始反转都不怕。
这个方法比较好理解一些。这题无非就是反转的地方有限制罢了,何不我先把要反转的部分断开来当作一个新链表,直接反转新链表,然后在接回去呢。
leftNode
和rightNode
。pre
和succ
,方便断开、接回。reverseList
用于反转某一链表就行了。整个过程示意图如下(蓝色为新链表):
单独用于反转链表的函数:
void reverseList(LinkNode* head) {
LinkNode* pre = nullptr;
LinkNode* cur = head;
while (cur != nullptr) {
LinkNode* next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
}
区间反转方法:
LinkNode* reverseBetween02(LinkNode* head, int left, int right) {
//创建虚拟头结点
LinkNode* dummyNode = new LinkNode;
dummyNode->next = head;
LinkNode* pre = dummyNode;
//从虚拟头结点开始走到要反转区间的前一个结点
for (int i = 0; i < left - 1; i++) {
pre = pre->next;
}
//rightNode指向right位置的结点
LinkNode* rightNode = pre;
for (int i = 0; i < right - left + 1; i++) {
rightNode = rightNode->next;
}
//leftNofe指向left位置的结点
LinkNode* leftNode = pre->next;
LinkNode* succ = rightNode->next;
//断开链表
pre->next = nullptr;
rightNode->next = nullptr;
//新链表的头结点是leftNode,反转它!
reverseList(leftNode);
//接回原链表中
pre->next = rightNode;
leftNode->next = succ;
return dummyNode->next;
}
这里要注意⭐的是:新链表反转完后的新头结点是rightNode
所指的结点,所以是pre->next = rightNode;
和leftNode->next = succ;
。
如果考虑代码的健壮性,其实还可以加入很多,比如:判断链表是否为空/只有一个结点、形参left一定要小于right且两者都要合法(不能超出链表长度/为负数)等等,这里为了代码简洁好看我就不加上去了哈。
伙计们,我们下篇再见✌️!