• 【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点始终未变
    }
  • 相关阅读:
    C# 图片与Base64的相互转化
    LeetCode 303. Range Sum Query – Immutable
    LeetCode 300. Longest Increasing Subsequence
    LeetCode 292. Nim Game
    LeetCode 283. Move Zeroes
    LeetCode 279. Perfect Squares
    LeetCode 268. Missing Number
    LeetCode 264. Ugly Number II
    LeetCode 258. Add Digits
    LeetCode 257. Binary Tree Paths
  • 原文地址:https://www.cnblogs.com/JesseTsou/p/9563700.html
Copyright © 2020-2023  润新知