题解 | #链表内指定区间反转#

链表内指定区间反转

https://www.nowcoder.com/practice/b58434e200a648c589ca2063f1faf58c

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param head ListNode类 
 * @param m int整型 
 * @param n int整型 
 * @return ListNode类
 */
struct ListNode* reverseBetween(struct ListNode* head, int m, int n ) {
    // write code here
    /**尝试使用进阶的解法,即原地翻转
    可以这样理解:在达到翻转起始位置之前正常遍历,当到达起始翻转位置时可以
    开始进行头插法每次截取其中一个点,以起始位置为头进行头插法,直到需要
    的结点全部完成头插为止,最后再处理后续链表,即直接连接到上述头插后链表
    的末尾即可*/
    if(head==NULL||m==n) return head;
    //对两种特殊情况直接进行返回,不需要进行翻转操作
    //struct ListNode* tmpHead=head;
    // for(int i=0;i<m-1;i++){
    //     tmpHead=tmpHead->next;
    // }//遍历找到当前不需要翻转的前段结点的尾部当做头插法的头
    //上述代码段在m==1的时候会出问题,因为缺少了首结点的前置结点,无法头插
    //解决方案是设置一个虚拟的头结点,在这个基础上进行翻转操作,
    //然后再重新组装回链表
    struct ListNode* tmpHead=(struct ListNode*)malloc(sizeof(struct ListNode));//开辟空间设置一个新的虚拟头结点,方便后续的头插操作
    tmpHead->next=head;//直接连接,统一处理,不需要额外讨论m=1的情况
    struct ListNode* p=tmpHead;
    //p指针的存在是用来找到待插前置结点的
    for(int i=0;i<m-1;i++){
        p=p->next;
    }
    struct ListNode* q=p->next;//q指示当前需要进行头插的结点
    struct ListNode* t=q->next;//t指示后续表链
    tmpHead->next=NULL;
    for(int i=0;i<=n-m;i++){
        q->next=tmpHead->next;//断链操作
        tmpHead->next=q;//头插操作
        q=t;
        if(t!=NULL)
            t=t->next;//重新找到下一个需要头插的结点
    }//表明有多少个点需要进行插入操作
    //进行终末处理和连接
        p->next=tmpHead->next;
        t=p->next;
        while(t->next!=NULL){
            t=t->next;
        }
        t->next=q;
        if(m==1)
            head=tmpHead->next;
            //该步骤必须在free之前,否则tmpHead以及p指针指向的的结点都消失了,会发生不可预料的错误(找不到真正的头,所有数据丢失)
        free(tmpHead);
        return head;
}

很显然对指针的掌握不够熟练,在书写代码上出了很多问题,指针悬空的问题,指针本身指向NULL却缺少判断的问题等

同时代码书写的也不够简洁美观,还需要更多的学习和练习来进一步提高水平

全部评论

相关推荐

Noob1024:一笔传三代,人走笔还在
点赞 评论 收藏
分享
Natrium_:这时间我以为飞机票
点赞 评论 收藏
分享
今天 13:29
已编辑
湖南铁道职业技术学院 后端
小红书 后端选手 n*16*1.18+签字费期权
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务