思路:其实递归解法是最容易的,不过尝试了一下非递归解法,尝试了n遍,-_-!。
逐段进行反转,注意如果元素不足k个,就不需要反转。主函数确定反转的前后位置,调用中间函数来完成反转功能,然后首先衔接好(这点最难),具体过程看代码的注释。
code:
class Solution {
public:
ListNode * reverseList(ListNode * &preEnd, ListNode *begin,ListNode *end,bool flag){
//preEnd 是前面反转好的链表的尾节点,需要连接到新反转的链表首节点;
//begin节点 到 end前一个节点是反转的范围,flag为true是才反转,否则不反转。
if(!flag){
if(preEnd!=NULL)
preEnd->next = begin;
return begin;
}
ListNode * curP=begin,*nextP = curP->next, *lastP;
while(nextP != end){
lastP = nextP->next;
nextP->next = curP;
curP = nextP;
nextP = lastP;
}
if(preEnd!=NULL)
preEnd->next = curP;
return curP;
}
ListNode *reverseKGroup(ListNode *head, int k) {
ListNode * end = head, *newEnd = head, *newBegin = head, *preEnd=NULL;
if(head == NULL || k == 1) return head; //不需要反转的情况
int m = k;
//确定反转后的首节点
while(--m){
if(newBegin->next == NULL)break;
newBegin = newBegin->next;
}
if(m>0) return head;
bool flag = true;
while(end!=NULL){
int n = k;
while(n--){
end = end->next;
if(end==NULL){
if(n>0) flag = false; //不需要反转,因为剩余的节点数目小于k
break;
}
}
ListNode * localBegin = reverseList(preEnd,newEnd,end,flag);
preEnd = newEnd; //将反转好的链表的尾节点更新
newEnd = end; //新的需要反转的链表的首节点(反转后变成尾节点)
}
//确定最后反转好的尾节点的下一个位置,如果反转过程中没有出现不需要反转的情况(即刚好都需要反转),需要另尾节点指空。
if(flag) preEnd->next = end;
return newBegin;
}
};
本文详细介绍了使用递归和非递归方法解决链表反转问题,通过逐步演示和代码注释,展示了如何在不同场景下实现链表的反转操作。重点在于理解两种方法的原理和实现细节,以及它们在不同情况下的适用性。
852

被折叠的 条评论
为什么被折叠?



