常作题,常更新。
这类题就是和反转链表有关,有两种思路,一种是维护几个指针顺着链表一个一个做处理。
这样效率比较高,但是确实比较繁琐。
另一个是用递归的思想来翻转链表,一层层递归下去,在函数出栈的时候让下一个节点的指针指向自己,因为使用了函数栈来记录每个节点的指针,所以代码实际上更简单了。
下面要要记录的是翻转链表的一个变体,即在链表中部分翻转链表。
下面是 25题的解,25题其实是24题的通用形式。
class Solution {
public:
int count;
ListNode* new_head; //新的头
ListNode* old_next; // 第K+1个节点
ListNode* pre; //前驱
bool partial_reverse(ListNode* p, int n)
{
if (p == nullptr) //没到数量就空了,说明不能翻转
{
return false;
}
if (n == count) //新的头部找到了,如果有前驱就把前驱的next指向它
{
old_next = p->next;
new_head = p;
//连上
if (pre)
{
pre->next = new_head;
}
return true;
}
if (partial_reverse(p->next,n+1)) //递归到下一层,没问题就把下一层的next指向这层
{
p->next->next = p;
if (n == 1)
{
p->next = old_next; //新尾巴指向原来的后驱
pre = p; //新尾巴变成前驱,为下k个链表的反转做准备。
}
return true;
}
else
{
return false;
}
}
ListNode* reverseKGroup(ListNode* head, int k) {
if (k == 0 || k == 1) return head;
count = k;
new_head = nullptr;
old_next = nullptr;
pre = nullptr;
ListNode* p = head;
ListNode* res = head;
int i = 0;
while(partial_reverse(p,1))
{
if (i == 0)
{
res = new_head;
i++;
}
p = old_next;
}
return res;
}
};
注意 partial_reverse()函数,这个函数会反转部分链表,返回反转情况,如果剩下的节点不够k个,就会反转失败,返回false
利用class的特性,这个函数得以简化,和他相关的参数 :
count 是 k,子链表长度, new_head即反转后子链表的新头部,
old_next是子链表尾部的next,毕竟是在一个链表里做部分反转,所以还是要记下来,
pre是子链表的前驱
示意图如下:
pre —— sub list —— old_next
之前老是忘记处理pre这个节点,pre->next记录的是反转前的头节点,如果反转后不把pre->next指向新的头节点,会导致整条链表丢节点。
本文介绍了一种局部反转链表的方法,通过递归实现,并详细解释了关键步骤和注意事项,如处理前驱节点以避免丢失链表节点。
437

被折叠的 条评论
为什么被折叠?



