zoukankan      html  css  js  c++  java
  • 【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点始终未变
    }
  • 相关阅读:
    Entity Framework Code First使用DbContext查询
    Entity Framework Code First执行SQL语句、视图及存储过程
    Entity Framework Code First关系映射约定
    Entity Framework Code First属性映射约定
    Entity Framework Code First数据库连接
    EF Power Tools参数不正确的解决方法
    EF Code First Migrations数据库迁移
    前端Js框架汇总【转】
    浅谈Hybrid技术的设计与实现【转】
    用于HTML5移动开发的10大移动APP开发框架【转】
  • 原文地址:https://www.cnblogs.com/JesseTsou/p/9563700.html
Copyright © 2011-2022 走看看