【leetcode】92 Reverse Linked List II

题目说明

https://leetcode-cn.com/problems/reverse-linked-list-ii/description/
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

解法1

首先遍历到m的前一个结点,由于m点可能处理第一个位置,所以需要创建虚拟头结点,指向m结点,然后反转[m,n]的结点。
反转结点:
1、记录当前点的下一个结点,防止下一点位置丢失
2、当前点的下一个结点指向前一个结点
3、前一个结点指向当前结点,为下一次反转作准备
4、当前结点指向下一个结点,即当前点后移
5、以上过程反复执行,即完成反转过程
注意:反转的第一个点(即m结点)的下一个结点需要指向最后一点(即n结点)的原来的下一结点,完成衔接。

/*
 * 时间复杂度:O(n)
 * 对于m=1的情况需要作特殊处理。
 */
ListNode* reverseBetween(ListNode* head, int m, int n) {
    ListNode *pm_pre = head;

    //记录m前一个结点
    for (int i = 1; i < m - 1; i ++){
        pm_pre = pm_pre->next;
    }

    //创建虚拟头结点,其下一个结点为m位置结点
    ListNode *newhead = new ListNode(0);
    if (m == 1)
        newhead->next = pm_pre;
    else
        newhead->next = pm_pre->next;

    //反转m至n的结点
    ListNode *pre = newhead;
    ListNode *cur = newhead->next;
    ListNode *next = NULL;
    ListNode *temp = cur;//m结点位置
    for (int i = m; i <= n; i ++){
        if (cur == NULL)
            break;
        next = cur->next;
        cur->next = pre;
        pre = cur;
        cur = next;
    }

    //将m结点的next指向原来n的下一个结点
    temp->next = cur;
    if (m == 1)
    {
        //若m==1,即n结点即头结点
        head = pre;
    }else{
        //将m前一个结点的next指向反转后的第一个结点(即n结点)
        pm_pre->next = pre;
    }
    delete newhead;
    return head;
}

解法2

以上方法还是过于冗余了,下面这种方法,是在链表头结点之前建立虚拟头结点。
遍历到m点之前,记录m前一点pre。
很巧妙的是,反转过程中,使用pre->next来记录当前点,即下一点的前一点。但对于m点,指向自身;对于(m,n]指向其前一点。这样就完成了对于m结点的特殊处理。
最后再将m点下一结点指向n的下一结点。完成衔接。

/*
 * 时间复杂度:O(n)
 * 创建虚拟头结点
 * 先将m的下一点指向自身,最后再处理m的下一个结点
 */
ListNode* reverseBetween(ListNode* head, int m, int n) {
    ListNode *dummy = new ListNode(0);
    dummy->next = head;
    ListNode *pre = dummy;
    //m点前一点pre
    for (int i = 1; i <=m - 1; i ++){
        pre = pre->next;
    }
    ListNode *cur = pre->next;
    ListNode *pm = cur;
    ListNode *next = NULL;
    for (int i = m; i <= n; i ++){
        next = cur->next;//记录当前点的下一点
        cur->next = pre->next;//对于m点,指向自身;对于(m,n]指向其前一点
        pre->next = cur;//记录当前点,即下一点的前一点
        cur = next;//当前点移动到下一点
    }
    pm->next = cur;//m点下一结点指向n的下一结点
    return dummy->next;//dummy点始终未变
}
原文地址:https://www.cnblogs.com/JesseTsou/p/9563700.html