这道题花了一点时间,一开始思路有点乱。以后还是要先写好思路再开始写代码。
思路:1.定义一个指针指向链表头,往后移动进行计数,翻转链表
这里判断用一个函数判断后面段链表能否进行翻转
2.将翻转完成的一段链表接到已翻转完成的链表后面
3.用rear记录已完成翻转部分的链表的尾,front记录刚刚完成翻转的小段链表的头
4.将完成翻转操作的小段链表的头接到已完成翻转部分的链表的尾上
5.将rear置为新链表的尾
6.进行以上操作,直到判断是否能翻转的函数返回false
一开始我以为设置一个函数来判断后面链表是不是可以翻转这种方法的时间复杂度太大了,没有考虑用这种方法,结果思路理乱了,其实也没有其他更好的方法了。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool canreverse(ListNode* head,int k)
{
ListNode* temp=head;
int i=0;
while(temp)
{
temp=temp->next;
++i;
}
return i>k||i==k;
}
ListNode* reverse(ListNode* &head,int n)
{
ListNode* p=NULL,*q=NULL;
while(n--&&head)
{
p=head;
head=head->next;
p->next=q;
q=p;
}
return q;
}
ListNode* reverseKGroup(ListNode* head, int k) {
if(!head||!head->next) return head;
if(!canreverse(head,k)) return head;
ListNode* Head,*front,*rear=head,*temp;
if(!canreverse(head,k)) return head;
front=reverse(head,k);
Head=front;
while(canreverse(head,k))
{
temp=head;
front=reverse(head,k);
rear->next=front;
rear=temp;
}
rear->next=head;
return Head;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverse(ListNode* &head,int n)
{
ListNode* p=NULL,*q=NULL;
while(n--&&head)
{
p=head;
head=head->next;
p->next=q;
q=p;
}
return q;
}
ListNode* reverseKGroup(ListNode* head, int k) {
if(!head||!head->next) return head;
ListNode* Head,*front,*rear=head,*temp=head;
int n=0;
while(temp&&++n) temp=temp->next;
n/=k;
if(n==0) return head;
front=reverse(head,k);
n--;
Head=front;
while(n--)
{
temp=head;
front=reverse(head,k);
rear->next=front;
rear=temp;
}
rear->next=head;
return Head;
}
};
优化后的代码,先算出链表的总长度,进而得出总共需要翻转的次数,这样省去了很多次遍历链表的操作。