思路一:无论链表的题目要求怎样删除节点, 修改节点指针等等,有一个几乎万能的方法可以简化题目。就是用哈希表为每一个节点映射。这样以下标的方式就很容易操作链表了。
class Solution {
public:
int num;
map<int, ListNode *>m;
ListNode *reverseKGroup(ListNode *head, int k) {
if(head == nullptr || head->next == nullptr || k < 2)
return head;
num = 0;//链表节点的数目
ListNode * p = head;
while(p){
m[num++] = p;//映射链表
p = p->next;
}
if( num/k == 0)//num < k
return head;
ListNode * res = solve(0, k - 1, k);//反转
return res;
}
//反转start-end这些节点的指针域
ListNode * solve(int start, int end, int k){
if(end >= num)//start-end的不能成为含有K个节点的一组,就是数目不够
return m[start];
for(int i = end; i > start; i--){//修改指针
m[i]->next = m[i - 1];
}
m[start]->next = solve(start + k, 2*k+start-1, k);//递归修改剩余未反转的
return m[end];//返回链表头部
}
};
思路二:别人做的,好精辟,空间复杂度常数级别。就是利用头插法来实现链表的节点反转。但是反转一段后记得保存前一段的尾部节点。用头插法来修改节点反转,真是没想到,数据结构还是学不好啊。
```cpp
class Solution {
public:
ListNode *reverseKGroup(ListNode *head, int k) {
if(head == nullptr || head->next == nullptr || k < 2)
return head;
int length = 0;
ListNode * phead = head;
while(phead){//统计链表长度
length++;
phead = phead->next;
}
ListNode * dummy = new ListNode (0);
dummy->next = head;//给链表接一个假的头节点。
ListNode * cur = head, *pre = dummy, * temp;
for(int i = 0; i < length /k; i++){
for(int j = 1; j < k; j++){
//下面都是头插法。
temp = cur->next;
cur->next = temp->next;
temp->next = pre->next;
pre->next = temp;
}
pre = cur;//前驱指针指向反转后的那一段的链表的尾部
cur = cur->next;//指向未修改的链表的头部
}
return dummy->next;
}
};