刷题笔记之链表内指定区间反转

此题是反转链表的进阶版,建议先做反转链表(反转链表的题解在上一个文章)。

话不多说先上代码: 

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @param m int整型 
     * @param n int整型 
     * @return ListNode类
     */
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        // write code here
        if(head==nullptr||head->next==nullptr||m==n) return head;
        ListNode* tmp1 = head;
        ListNode* tmp2 = head;
        //tmp1保持反转的起始位置
        for(int i=0;i<m-1;i++){
            tmp1 = tmp1->next;
        }
        //tmp2保存反转的结束位置的下一个
        for(int i=0;i<n;i++){
            tmp2 = tmp2->next;
        }
        //开始反转
        ListNode* a = nullptr;
        ListNode* b = tmp1;
        ListNode* c = tmp1->next;
        for(int i=0;i<n-m+1;i++){
            b->next = a;
            a = b;
            b = c;
            if(b == tmp2) break;
            c = c->next;
        }
        ListNode* tmp3 = nullptr;//用于连接
        ListNode* newList = nullptr;//返回结果的表头
        if(m>=2){//若反转位置不包括头节点
            tmp3 = head;//那么让tmp3初始为头节点
            newList = tmp3; //返回结果的表头记录一下tmp3,因为后面tmp3要进行连接向后走
            //让tmp3从头走到反转位置的前一个
            for(int i=0;i<m-2;i++){
                tmp3 = tmp3->next;
            }
            tmp3->next = a;//再与反转后的链表相连 
        }
        else{//如果反转位置包括头节点,那就让tmp3直接等于反转后的链表
           tmp3 = a;//反转位置包括头节点那么头节点也被反转了,所以新的头就是反转后链表的头
           newList = tmp3; //返回结果的表头记录一下tmp3,因为后面tmp3要进行连接向后走
        }
        //最后让tmp3的尾部与tmp2相连
        while (tmp3->next!=nullptr) {
            tmp3 = tmp3->next;
        }
        tmp3->next = tmp2;
        return newList;//返回结果
    }
};

解题思路:

首先,我们要先得到反转那部分的链表。

定义两个标记指针,tmp1:保存反转的起始位置,tmp2:保存反转的结束位置的下一个。

ListNode* tmp1 = head;
ListNode* tmp2 = head;
//tmp1保持反转的起始位置
for(int i=0;i<m-1;i++){
    tmp1 = tmp1->next;
}
//tmp2保存反转的结束位置的下一个
for(int i=0;i<n;i++){
    tmp2 = tmp2->next;
}

对那部分的链表进行反转,此时前面标记的两个指针就起到作用了,tmp1用于确定反转部分链表的头,tmp2用于最后判断是否已经完成反转。

//开始反转
ListNode* a = nullptr;
ListNode* b = tmp1;
ListNode* c = tmp1->next;
for(int i=0;i<n-m+1;i++){
    b->next = a;
    a = b;
    b = c;
    if(b == tmp2) break;
    c = c->next;
}

完成了反转就可以开始连接了,这时候又需要两个指针,tmp3用于进行连接,newList用于返回结果,先判断反转的链表包不包括原链表的头节点,如果不包括头节点:tmp3和newList都标记原链表的头,然后让tmp3从头走到反转位置的前一个再与反转后的链表相连,如果包括头节点:那就让tmp3和newList直接等于反转后的链表头即a指针,因为此时的a已经确定为最终结果的头节点了(原来的头结点被转后面去了)。

ListNode* tmp3 = nullptr;//用于连接
ListNode* newList = nullptr;//返回结果的表头
if(m>=2){//若反转位置不包括头节点
    tmp3 = head;//那么让tmp3初始为头节点
    newList = tmp3; //返回结果的表头记录一下tmp3,因为后面tmp3要进行连接向后走
    //让tmp3从头走到反转位置的前一个
    for(int i=0;i<m-2;i++){
        tmp3 = tmp3->next;
    }
    tmp3->next = a;//再与反转后的链表相连 
}
else{//如果反转位置包括头节点,那就让tmp3直接等于反转后的链表
    tmp3 = a;//反转位置包括头节点那么头节点也被反转了,所以新的头就是反转后链表的头
    newList = tmp3; //返回结果的表头记录一下tmp3,因为后面tmp3要进行连接向后走
}

最后让tmp3的尾部与tmp2相连,返回结果newList。

//最后让tmp3的尾部与tmp2相连
while (tmp3->next!=nullptr) {
    tmp3 = tmp3->next;
}
tmp3->next = tmp2;
return newList;//返回结果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值