题目描述
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
递归算法
//结点类型
class ListNode
{
int val;
ListNode* next;
}
1、首先对整个链表反转
ListNode* reverse(ListNode* head)
{
if(head->next == nullptr)
{
return head;
}
ListNode*last = reverse(head->next);
head->next->next = head;
head->next = nullptr;
return last;
}
2、对链表的前n个结点反转
ListNode* successer = nullptr;
ListNode* reverseN(ListNode* head, int N)
{
//判断条件修改
if(N == 1)
{
successer = head->next;
return head;
}
ListNode*last = reverseN(head->next, N - 1);
head->next->next = head;
head->next = successer;
return last;
}
3、对链表的第m - n个结点实现反转
ListNode* reverseBetween(ListNode* head, int M, int N)
{
//判断条件修改
if(M == 1)
{
return reverseN(head, N);
}
head->next = reverseBetween(head->next, M - 1, N - 1);
return head;
}
方法总结
不要跳进递归,而是利用明确的定义来实现算法逻辑。
例如实现算法1、reverse时,直接将head之后看为一块已经反转的部分,指针last指向这一块的头部,所以需要做的是将这一块的尾部next指针(即head->next->next)指向head,然后head->next指向nullptr即可实现反转,最后返回last即可。
关于递归算法的书写
1、首先要有base case,就是子方法的情况需要考虑退出或者返回相应值
2、状态转移函数,递归调用
3、返回谁
迭代算法
1、首先对整个链表反转
// 反转以 a 为头结点的链表
ListNode reverse(ListNode a) {
ListNode pre, cur, nxt;
pre = null; cur = a; nxt = a;
while (cur != null) {
nxt = cur.next;
// 逐个结点反转
cur.next = pre;
// 更新指针位置
pre = cur;
cur = nxt;
}
// 返回反转后的头结点
return pre;
}
2、前n个结点的反转,左闭右开
/** 反转区间 [a, b) 的元素,注意是左闭右开 */
ListNode reverse(ListNode a, ListNode b) {
ListNode pre, cur, nxt;
pre = null; cur = a; nxt = a;
// while 终止的条件改一下就行了
while (cur != b) {
nxt = cur.next;
cur.next = pre;
pre = cur;
cur = nxt;
}
// 返回反转后的头结点
return pre;
}
感觉labuladong算法这里有一个bug,没有把链表连起来。是否应该在返回前执行
a.next = cur; //因为此时cur==b
上述代码实现了b之前的部分的反转,但是a.next此时为nullptr,应该让a指向b位置结点,返回pre即可得到反转的数组