leetcode - Reverse Linked List

Reverse Linked List I

思路:

题目中有提示两种思路:迭代和递归。迭代的思路比较简单,可以直接在原链表上面操作,定义三个指针分布指向链表的相邻的三个节点,最后三个指针都从头开始顺序往下滑动,直到最后一个指针最先滑动到NULL为止。在滑动过程中不断地把中间节点的next指针指向pre(第一个指针);递归的思路更加直观,不过运行速度会比较慢。因为增加了函数调用和比较的过程。假设头节点的下一个节点作为链表的子链表的反转链表已经求出,那么就只有把头节点的next置为NULL,然后把子链表的反转链表的尾节点的next置为头节点就好。

注意:

head的next指针要置为NULL

代码:

    //iteratively
    ListNode* reverseList(ListNode* head)
    {
        //special cases
        if(!head || !(head -> next)) return head;
        //Three Pointers
        ListNode *pre = head, *p = head -> next, *nxt = p -> next;
        pre -> next = NULL;
        p -> next = pre;
        while(nxt)
        {
            pre = p;
            p = nxt;
            nxt = nxt -> next;
            p -> next = pre;        
        }
        return p;
    }

    //recursively
    ListNode* reverseList(ListNode* head) {
        //end condition
        if(!head || !(head -> next)) return head;
        //recursion
        ListNode *reversePointer = reverseList(head -> next), *tmp = reversePointer;
        while(tmp -> next)
        {
            tmp = tmp -> next;
        }
        tmp -> next = head;
        head -> next = NULL;
        return reversePointer;
    }

Reverse Linked List II

思路:

和第一题类似,只是情况扩展了一下,包含了第一题。我的想法是把m和n对应的子链找出来,放到第一题的函数中求出反转以后再加入之前的链表中(找出第m个节点的上一个节点和第n个节点的下一个节点)。反转后的子链的头接入第m个节点的上一个节点的next,反转后子链的尾的next接入第n个节点的下一个节点。不过速度比较慢,应该有更好的方法。

注意:

必须在原来链表上操作,并且只能遍历链表一遍,所以有了代码2

代码:

    ListNode* reverseList(ListNode* head)
    {
        if(!head || !(head -> next)) return head;
        ListNode *pre = head, *p = head -> next, *nxt = p -> next;
        pre -> next = NULL;
        p -> next = pre;
        while(nxt)
        {
            pre = p;
            p = nxt;
            nxt = nxt -> next;
            p -> next = pre;        
        }
        return p;
    }
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        //特殊情况处理
        if(!head || !(head -> next) || m == n) return head;

        ListNode *mPre = NULL, *nNxt = head -> next, *mPointer = head, *nPointer = head;
        while(--m)
        {
            mPre = mPointer;
            mPointer = mPointer -> next;

        }
        while(--n)
        {
            nPointer = nPointer -> next;
            nNxt = nPointer -> next;
        }
        nPointer -> next = NULL;
        ListNode *rePointer = reverseList( mPointer);
        if(nNxt)
        {
            ListNode *reTailPointer = rePointer;
            while(reTailPointer -> next)
            {
                reTailPointer = reTailPointer -> next;
            }
            reTailPointer -> next = nNxt;
        }

        if(mPre)
        {
            mPre -> next = rePointer;
            return head;
        }
        return rePointer;      
    }

代码2:

    ListNode* reverseBetween(ListNode* head, int m, int n)    {
        //特殊情况处理
        if(!head || !(head -> next) || m == n) return head;
        int mn = n - m;
        ListNode *mPre = NULL, *mPointer = head, *nPointer;
        //找到开始反转的点
        while(--m)
        {
            mPre = mPointer;
            mPointer = mPointer -> next;
        }
        //
        nPointer = mPointer;
        //开始一边找n一边反转,mn >= 1
        ListNode *pre = mPointer, *p = mPointer -> next, *nNxt = p -> next;
        pre -> next = NULL;
        p -> next = pre;
        while(--mn)
        {
            pre = p;
            p = nNxt;
            nNxt = nNxt -> next;
            p -> next = pre; 
        }
        //nPointer -> next = NULL;
        //把对应的不用反转的链表接上
        if(nNxt)
        {
            ListNode *reTailPointer = p;
            while(reTailPointer -> next)
            {
                reTailPointer = reTailPointer -> next;
            }
            reTailPointer -> next = nNxt;
        }

        if(mPre)
        {
            mPre -> next = p;
            return head;
        }
        return p;      
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值