[LeetCode] Reverse Linked List II(!!!)

57 篇文章 0 订阅
2 篇文章 0 订阅

Reverse Linked List II Reverse a linked list from position m to n. Do
it in-place and in one-pass.

For example: Given 1->2->3->4->5->NULL, m = 2 and n = 4,

return 1->4->3->2->5->NULL.

Note: Given m, n satisfy the following condition: 1 ≤ m ≤ n ≤ length
of list.

将[m,n]之间的结点反转

思路一

类似于将整个链表反转,pPrev,pNode,为头两个结点,每次将pNode指向pPre,再将pPre和pNode向后移动即可。反转链表
在本例中,结束的条件不是pNode ==NULL,而是结点的数目n-m+1;

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        int k = n-m+1;
        ListNode *new_head = new ListNode(0);
        new_head->next = head;
        ListNode* pre = new_head;
        //pre实际上是第m-1个结点
        for (int i = 0; i < m - 1; i++)
            pre = pre -> next;
        pre->next = reverseAll(pre->next, k);
        return new_head->next;

    }
    ListNode* reverseAll(ListNode* p1, int k){
        ListNode* pNode= p1;
        ListNode* pPrev=NULL;    //当前节点的前一个结点
        ListNode* pNext;
        //每次将pNode指向pPre;
        while(k--){
            pNext = pNode->next;
            pNode->next = pPrev;
            //移动pNode和pPre
            pPrev = pNode;
            pNode =pNext;
        }
        p1->next = pNode;   //实际上是第n+1个结点
        return pPrev;
    }
};

上面的reverseAll函数如果将形参k去掉,while变成while(pNode!=NULL)则是一个普通的反转链表。
注意while退出时,pNode指向的是第n+1个结点(有k的情况)或是NULL(没有k的情况)。这是需要把原始的头结点p1->next = pNode;
另一个小的trick就是不用考虑m=1的特殊情况,只需要再加一个new_head的头结点即可。
0ms AC

思路二

Jianchao’s Blog 大神每次都能给出牛逼的思路

class Solution {  
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        ListNode* new_head = new ListNode(0);
        new_head -> next = head;
        ListNode* pre = new_head;
        for (int i = 0; i < m - 1; i++)
            pre = pre -> next;
        ListNode* cur = pre -> next;
        for (int i = 0; i < n - m; i++) {
            ListNode* move = cur -> next; 
            cur -> next = move -> next;
            move -> next = pre -> next;
            pre -> next = move;
        }
        return new_head -> next;
    }
};

pre指向第m-1个结点,curr是当前的结点,move是m+1个结点,我们每次都将curr的next指向curr的next的next,将move指向curr,将pre指向move。注意pre是不动的,每次因为curr的next都在变,所以一直移动。
4ms AC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值