给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明 :
- 你的算法只能使用常数的额外空间。
- 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
思路:我的思路就是将链表分开成组,压入vector中,按照实际情况判断是否需要翻转。当小组中的节点数小于k值时不用翻转。最后一并输入,上一组最后一个结点连接下一组的头结点。
注意保存返回的头结点。
(我的代码效率实在太低,有些汗颜,需要多多学习!)
另外两个注意的:
在cuts[m+1]这个语句中,会报错,free() invalid pointer。因为存在越界访问的行为,需要注意
对于链表翻转的算法还需加强理解和练习。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
//实验:将链表切断;--可以切断的
vector<ListNode*> cuts;
ListNode* p=head;
ListNode* r=head;
int cnt=0;
int sum=0;
while(p!=NULL){
p=p->next;
sum++;
}
if(sum==k)
return ReverseList( head) ;
p=head;
int i=0;//判断分组;
int j=0;//判断最后一个组是否需要翻转
int l=0;//统计分组数;
while(p!=NULL){//分组,压入vector中;
cnt+=i;
i=0;
for(i;i<k;i++){
// cout<<"1"<<endl;
cout<<p->val<<endl;
r=p;
if((sum-cnt)<k){
break;
}
p=p->next;
}
if((sum-cnt)>k){
j=1;//不需要翻转
r->next=NULL;
}
cuts.push_back(head);
++l;//统计分组数
head=p;
if((sum-cnt)<k){
break;
}
//cout<<"2"<<endl;
}
for(auto &t:cuts){//判断该组是不是需要翻转;
int sum=0;
ListNode *p=t;
while(p!=NULL){
p=p->next;
sum++;
}
if(sum==k)
t= ReverseList(t);
}
//将各组连接;
// cout<<l<<endl;
int m=0;
for(auto &t:cuts){
if(m==0)
head=t;
p=t;
while(p->next!=NULL){
p=p->next;
}
if(m+1<l)
p->next=cuts[m+1];
else
break;
++m;
}
return head;
}
private:
ListNode* ReverseList(ListNode* pHead) {
ListNode *root=pHead;
ListNode *pre=NULL;
ListNode *next=NULL;
if(pHead==NULL) return NULL;
while(root->next){
next=root->next;
root->next=pre;
pre=root;
root=next;
}
root->next=pre;
return root;
}
};