[lintcode]36. 翻转链表 II

链接:http://www.lintcode.com/zh-cn/problem/reverse-linked-list-ii/

翻转链表中第m个节点到第n个节点的部分

 注意事项

m,n满足1 ≤ m ≤ n ≤ 链表长度

您在真实的面试中是否遇到过这个题? 
Yes
样例

给出链表1->2->3->4->5->null, m = 2 和n = 4,返回1->4->3->2->5->null

思路

n-place翻转。首先找到所制定的区间(端点),然后翻转区间,最后实施重连。不需要额外的空间。

  1. 创建dummy node,记下head;提醒一下,如果是C++,为了避免内存泄漏,创建dummy node时最好不要用ListNode *dummy = new ListNode(0),而是创建结构体:ListNode dummy(0),最后通过dummy.next返回。
  2. 通过一次遍历,找到第m个节点mth,第m个节点的前一个节点mth_prev,第n个节点,第n个节点的后一个节点nth_next
  3. 翻转指定区间的链表段(同翻转整个链表的方法)。一种方法是,先nth->next=NULL,然后调用Reverse Linked List的方法,输入为mth
  4. 重新连接链表。这时指定区间的链表已经反向,把mth_prevnth相连,mthnth_next相连。
  5. /**
     * Definition of singly-linked-list:
     * class ListNode {
     * public:
     *     int val;
     *     ListNode *next;
     *     ListNode(int val) {
     *        this->val = val;
     *        this->next = NULL;
     *     }
     * }
     */
    
    class Solution {
    public:
        /**
         * @param head: ListNode head is the head of the linked list 
         * @param m: An integer
         * @param n: An integer
         * @return: The head of the reversed ListNode
         */
        ListNode * reverseBetween(ListNode * head, int m, int n) {
            // write your code here
            if(!head || !head->next)
                return head;
            ListNode* dummy = new ListNode(-1);
            dummy->next=head;
            ListNode* mth,*nth,*mth_prev=dummy,*nth_next;
            for(int i=1;i<n;i++)
            {
                if(i==m-1)
                    mth_prev=head;
                head=head->next;
            }
            
            mth=mth_prev->next;
            nth=head;
            nth_next=nth->next;
            
            nth->next=NULL;
            reverse_list(mth);
            mth_prev->next=nth;
            mth->next=nth_next;
            
            return dummy->next;
        }
        
        void reverse_list(ListNode *head)
        {
            ListNode *prev=NULL;
            while(head)
            {
                ListNode* next=head->next;
                head->next=prev;
                prev=head;
                head=next;
            }
        }
    };

class Solution {
public:
    /**
     * @param head: ListNode head is the head of the linked list 
     * @param m: An integer
     * @param n: An integer
     * @return: The head of the reversed ListNode
     */
    ListNode * reverseBetween(ListNode * head, int m, int n) {
        // write your code here
        if(!head || !head->next)
            return head;
        ListNode dummy(-1);
        dummy.next=head;
        ListNode* mth,*nth,*mth_prev=&dummy,*nth_next;
        for(int i=1;i<n;i++)
        {
            if(i==m-1)
                mth_prev=head;
            head=head->next;
        }
        
        mth=mth_prev->next;
        nth=head;
        nth_next=nth->next;
        
        nth->next=NULL;
        reverse_list(mth);
        mth_prev->next=nth;
        mth->next=nth_next;
        
        return dummy.next;
    }
    
    void *reverse_list(ListNode *head)
    {
        ListNode *prev=NULL;
        while(head)
        {
            ListNode* next=head->next;
            head->next=prev;
            prev=head;
            head=next;
        }
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值