Reverse Linked List II

45 篇文章 0 订阅
18 篇文章 0 订阅

题目:Reverse a linked list from position m to n. Do it in-place and in one-pass.

先复习一下普通的翻转链表的头插法:

3个变量,head2,新头;cur,遍历变量,next保存需要遍历的下一个结点。4句话。

next= cur->next;
cur->next=head2;
head2=cur;
cur=next;

Reverse Linked List || 的基本框架也是头插法,因为翻转的是链表的一部分,还要考虑和整个链表的连接问题。

1)首先考虑父链表和子链表头的对接问题:

因为头插法里head2变量始终存放翻转后链表头,只需把m-1节点指针域用作head2变量就可以了,对接始终保持。

2)子链表尾和父链表的的对接问题:

最后的状态应该是m节点作为子链表尾与父链表对接,所以可以考虑把m节点的指针域用作next变量。所以这里的头插法从第二个节点(m+1处)开始。

3)总结:算法的主框架就是头插法reverse 链表,只是要用m-1结点指针域作为head2变量, m结点指针域作为next变量, cur指针从m+1节点开始到n节点。如果m=1怎么办?这时候不存在m-1节点。解决办法:dummy节点。

ListNode *reverseBetween(ListNode *head, int m, int n) {
        ListNode dummy(-1), *prevM = &dummy;
        dummy.next = head;
        for (int i = 0; i < m - 1 && prevM; ++i, prevM = prevM->next) ;
        if (!prevM || !prevM->next || !prevM->next->next) return head;
        auto &head2 = prevM->next, mNode = prevM->next;
        auto &next = mNode->next, cur = mNode->next;
        for (int i = m + 1; i <= n && cur; ++i) {
            next = cur->next;
            cur->next = head2;
            head2 = cur;
            cur = next;
        }
        return dummy.next;
    }

一个更清晰的版本:就是把[m, n]节点一个个插入新链表。

ListNode *reverseBetween(ListNode *head, int m, int n) {
    ListNode dummy(-1), *prevM = &dummy;
    dummy.next = head;
    for (int i = 0; i < m - 1 && prevM->next; ++i, prevM = prevM->next) ;
    if (!prevM->next) return head;
    auto &head2 = prevM->next, cur = prevM->next, start = prevM->next;
    for (int i = m; i <= n && cur; ++i) {
        auto next = cur->next;
        cur->next = head2;
        head2 = cur;
        cur = next;
    }
    start->next = cur;
    return dummy.next;
}
还是递归逻辑最清晰

ListNode *reverseBetween(ListNode *head, int m, int n) {
	if (head == nullptr || m >= n) return head;
    if (m > 1) {
        head->next = reverseBetween(head->next, m - 1, n - 1);
        return head;
    }
    ListNode *head2, *p = head;
    for (; n > 0 && p; --n) {
        auto next = p->next;
        p->next = head2;
        head2 = p;
        p = next;
    }
    head->next = p;
    return head2;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值