这个是个“困难”级别的题目,题目描述如下:
给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
为了解决这个问题,我想需要思考下面的问题
(1)如何知道翻转了多少组
(2)每一组的翻转需要记录那些节点才能保证后面组的翻转能够正确执行
1、为了解决问题(1),先遍历一遍链表求出整个链表的长度len,知道了len,那么就可以知道翻转了多少组了
int len=0;
while(now!=null)
{
len++;
if(len==k)
newHead=now;
now=now.next;
}
//now回到头,表示现在遍历的节点
now=head;
//翻转的组数次turnNumber
int turnNumber=len/k;
2、知道了遍历的组数之后,进行第二次变量,并且为了保证每一组翻转之后都能够继续正确的执行下去,遍历过程中需要记录以下节点。
(1)前一组翻转之后的尾节点beforeLast
(2)目前翻转组翻转之后的头节点partHead
(3)目前翻转组翻转之后的尾节店partLast
而在翻转过程中,需要记录的节点有:
(1)目前遍历的节点now
(2)目前遍历节点的前一个节点pre
解决了这两个问题之后,问题就迎刃而解了,每一组的处理过程如下:
(1)因为最一开始的now就是翻转之后的这个组的尾节店,所有partLast=now
(2)这一组不断的翻转,然后把最后一点节点设为partHead
(3)翻转这个组之后,把beforeLast.next指向partHead,然后partLast就是新的beforeLast
具体的代码如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
//先遍历一遍得到链表的长度len和翻转之后的头节点
ListNode now=head;
ListNode newHead=now;
int len=0;
while(now!=null)
{
len++;
if(len==k)
newHead=now;
now=now.next;
}
//now回到头,表示现在遍历的节点
now=head;
//翻转的组数次turnNumber
int turnNumber=len/k;
//beforeLast表示之前部分的尾部
ListNode beforeLast=null;
ListNode pre=null;
for(int i=0;i<turnNumber;i++)
{
//partLast表示每一部分翻转之后的头部,partHead表示头
ListNode partHead=null;
ListNode partLast=now;
int nowK=1;
while(nowK<=k)
{
if(nowK==k)
partHead=now;
nowK++;
ListNode nowNext=now.next;
now.next=pre;
pre=now;
now=nowNext;
}
if(beforeLast!=null)
beforeLast.next=partHead;
beforeLast=partLast;
}
if(beforeLast!=null)
beforeLast.next=now;
return newHead;
}
}
提交结果如下
上面即为个人的非递归解法