题解 | #链表内指定区间反转#
链表内指定区间反转
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却缺少判断的问题等
同时代码书写的也不够简洁美观,还需要更多的学习和练习来进一步提高水平