题目
分析
1. 方法一:题目中提到可以采用常数量个空间,所以想到了,采用一个大小为k的数组空间来存储group值,然后利用遍历k步前记录的链表起始地址,来修改这个k-Group链表的值。(修改的是链表中存储的值,而非链表指针)
2. 方法二:先遍历k步,记录k-Group链表的起始地址,和终止地址,然后调用一个链表翻转的子函数,对这个记录下起始地址和终止地址的链表翻转操作。(需要遍历两遍链表)
方法一
C代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseKGroup(struct ListNode* head, int k) {
//传参有效性判断
if(head==NULL || k<=0){
return head;
}
//申请一个k大小的数组
int value[k];
struct ListNode* p = head;
struct ListNode* pGroup = head;
int i = 0;
while(p != NULL){
value[i] = p->val;
if(i == (k - 1)){
int j = 0;
while(j < k){
pGroup->val = value[k-1-j];
j++;
pGroup = pGroup->next;
}
pGroup = p->next;
}
i = (i + 1) % k;
p = p->next;
}
return head;
}
C++代码
编程注意事项 : 链表操作时候,一定要先确定需要修改的是哪几个指针,在指针修改时候,确保不会因为修改了当前的指针,断了与后面链表的连接。
/**
* 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) {
if(head==NULL || k <= 0){ //传参有效性判断
return head;
}
int* value = new int[k];
ListNode* p = head;
ListNode* pGroup = head;
int i = 0;
while(p != NULL){
value[i] = p->val;
if(i == (k-1)){ //已经遍历k个数
int j = 0;
while(j < k){
pGroup->val = value[k-1-j];
j++;
pGroup = pGroup->next;
}
pGroup = p->next;
}
i = (i + 1) % k;
p = p->next;
}
delete [] value;
return head;
}
};
方法二
C代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseKGroup(struct ListNode* head, int k) {
//传参有效性判断
if(head==NULL || k<=1){
return head;
}
struct ListNode* pStart = head; //最终连接完的总链表
struct ListNode* pEnd = NULL;
struct ListNode* pStartK = head;
struct ListNode* pEndK = NULL;
struct ListNode* pNextK = head;
int i = 0;
while(head != NULL){
if(i==(k-1)){ //找到k个节点,需要翻转
pEndK = head;
pNextK = head->next; //保存需要翻转的k个节点后面链表地址
struct ListNode* tmp = NULL;
struct ListNode* current = pStartK;
while(current != pNextK){
tmp = current->next;
current->next = pEndK;
pEndK = current;
current = tmp;
}
if( pEnd==NULL){ //将翻转完的子链表链接到已经翻转完的整体链表上
pStart = pEndK;
pEnd = pStartK;
}else{
pEnd->next = pEndK;
pEnd = pStartK;
}
pEnd->next = pNextK; //将未翻转的链表链接到已经翻转的后面
pStartK = pNextK;
i = (i + 1) % k;
head = pNextK;
}else{
i = (i + 1) % k;
head = head->next;
}
}
return pStart;
}
C++代码
/**
* 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) {
if(head==NULL || k <= 0){ //传参有效性判断
return head;
}
ListNode* pStart = head; //总体链表的头尾指针
ListNode* pEnd = NULL;
ListNode* pkStart = head; //处理中的kGroup链表头尾指针
ListNode* pkEnd = NULL;
ListNode* pkNext = head; //待处理的链表头指针
int i = 0;
while(head != NULL){
if(i == (k-1)){
pkEnd = head;
pkNext = head->next; //后面还没有处理的链表起点地址
ListNode* current = pkStart; //翻转从pkStart到pkEnd之间的链表
ListNode* tmp = NULL; //翻转完,pkEnd变成是子链表的头结点,pkStart变成是子链表的末尾节点
while(current != pkNext){
tmp = current->next;
current->next = pkEnd;
pkEnd = current;
current = tmp;
}
if(pEnd == NULL){ //将刚翻转完的子链表链接到总体链表上面
pStart = pkEnd;
pEnd = pkStart;
}else{
pEnd->next = pkEnd;
pEnd = pkStart;
}
pEnd->next = pkNext; //后面还没有处理的链表链接到已经处理完的链表末尾
pkStart = pkNext;
i = (i+1)%k;
head = pkNext;
}else{
i = (i+1)%k;
head = head->next;
}
}
return pStart;
}
};