看到这个本周热度排名前三的题目,赶紧刷起来。 --1月29日
这个题目还是颇花费了一些脑细胞的,共计两个小时。--2月2日
本题主要考察链表的熟悉掌握和思维能力。
题目描述
将给出的链表中的节点每k 个一组翻转,返回翻转后的链表
如果链表中的节点数不是k 的倍数,将最后剩下的节点保持原样
你不能更改节点中的值,只能更改节点本身。
要求空间复杂度O(1)
例如:
给定的链表是1- - >2- - >3- - >4- - >5
对于k=2, 你应该返回 2- - > 1- - >4- - >3- - >5
对于k=3, 你应该返回 3- - >2 - - >1- - > 4- - > 5
一、分析题目
题目中有两处关键点:
关键点①:每k个翻转
关键点②:不够k个不翻转
在解题过程中,时刻把握这两条,就能够满分AC本题了。
我们做出如下规定,称原链表为链表1,反转后的链表为链表2。题目即要求我们编程达到如下。
二、思路策略
明确以下4个编程关键处理策略。
①按段依次处理。
因为段为基本的翻转单位。
②为链表2新建多余头节点。
(为了方便后续插入节点)
③检查是否该段够k个。
(为了实现每k个翻转,不够k个不翻转)
④每段处理完成后,将该段连接到链表2。
编程实现如下图(链表1为1- - >2- - >3- - >4- - >5; k=2)
三、代码
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param head ListNode类
* @param k int整型
* @return ListNode类
*/
ListNode* reverseKGroup(ListNode* head, int k) {
// write code here
/* 称原链表为链表1,反转后的链表为链表2*/
ListNode *now;/*遍历链表时,当前指向的节点*/
ListNode *now1;/*遍历链表时,当前指向的节点的下一个节点*/
ListNode *new_head = NULL;/*反转后链表的头指针*/
ListNode *new_head1 = NULL;/*反转后链表当前段的头指针*/
int num = 0;/*当前为这段的第num个节点,每段k个节点*/
/* 新建一个多余头节点*/
new_head = new ListNode(NULL);
new_head1 = new_head;
now = head;
while(now != NULL)
{
if(num == 0)
{
/* 不足k个的段不用反转 */
ListNode *p1 = NULL;
p1 = now;
int pnum = k;
while((p1 != NULL)&&(pnum >= 0))
{
p1 = p1->next;
pnum--;
}
if(pnum > 0)
{
new_head1->next = now;
break;
}
}
now1 = now->next;
/* 将now指向的节点从链表1取出*/
now->next = NULL;
/* 将now指向的节点插入链表2 new_head1处后*/
now->next = new_head1->next;
new_head1->next = now;
/* 将now指向链表1中第一个节点*/
now = now1;
num++;
/* 当前段的k个都反转完成后 */
if(num == k)
{
while(num > 0)
{
new_head1 = new_head1->next;
num--;
}
}
}
new_head = new_head->next;
return new_head;
}
};
四、淌过的坑
①链表1不足k个的情况
测试数据:
链表1 : 1- - >NULL k=2
注意“检查是否该段够k个”代码段的位置。
②链表1只k个的情况,即只有一段
测试数据:
链表1 : 1- - > 2 - - > NULL k=2
注意new_head连接。