思路:模拟
这道题其实不难在算法,因为这道题根本就没有所谓的算法,而只有所谓的模拟和代码能力的体现。
我们看题目,说是k个一组进行翻转,但是不足k个的那一组的顺序保持不变。如果我们选择一个一个的翻转,那么,当我们并不知道是不是在不足k个那一组的时候就进行了翻转,导致我们的顺序失调。因为链表本身就是不知道长度的。所以我们不能挨个去翻转,而是选择一组一组去翻转。
但是怎么翻转呢?我们首先需要知道链表的总长度,这样我们才能知道到底有多少组k个元素。所以我们需要首先把链表遍历一遍,然后我们求出来长度。这里的长度用处就是用来计算有多少组的,所以可以len%k求余,之后用(len-len%k)/k就是有多少组。这里作者没用,直接计数器满足count==len-len%k,其实是等价的。
这里需要几个特判:
1.如果链表本身就是空的,那么就直接null;
2.如果链表的长度并不足k个一组,那么直接返回原来的链表即可;
3.如果k==1,也没有翻转的必要,还是返回原来的链表。
好了,解决这些特殊因素之后,我们开始模拟:
我们会发现,如果只在原链表上不好改地址,这里作者投机取巧定义了一个栈。为什么用栈呢?先进后出,我们可以用这个特点来翻转,先出来的元素肯定翻转之后链表的头,最后的当然就是尾了。但是我们这里是k个一组,所以并不能下定结论这一组就是第一组,并且尾的指向并不明,因为下一组还没有进行翻转,所以我们又定义了一个集合list,只用来存储头和尾(存储的顺序不能颠倒),这样可以保证集合的长度是偶数,并能够有序的取出并修改指针。
定义指针指向原来链表,指到一个结点就count++,如果count不满足count%k==0,那么入栈。满足,我们就开始处理。用出栈的元素指向栈顶的元素,就相当于是翻转了。之后再进行更新,再这样操作......
然后,当我们count==len-len%k的时候,也就是到最后一组未翻转前的尾元素时,我们需要记录它的下一个元素,因为它的下一个元素那一组是不足k个的一组,所以我们需要知道它的第一个结点,之后修改指针用来指向它。
之后,我们在集合list中遍历,注意,是从第一组翻转后的尾元素开始,也就是下标为1,指向它的下一个元素,也就是第二组翻转后的头元素。依次类推...最后一组翻转后的尾元素就指向我们刚刚存储的不足k个元素的那一组的头元素,最后返回集合的0下标元素,即第一组翻转后的头元素就行了。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if(head==null)
return null;
int len=0;
ListNode tmpp=head;
while(tmpp!=null){
len++;
tmpp=tmpp.next;
}
if(len<k||k==1)
return head;
List<ListNode>list=new ArrayList<ListNode>();
Deque<ListNode>stk=new LinkedList<ListNode>();
ListNode cnt=head;
int count=0;
int cha=len%k;
ListNode cao=new ListNode(-1);
while(cnt!=null&&count<len-cha){
count++;
ListNode cnt_next=cnt.next;
if(count%k!=0){
stk.push(cnt);
}
else{
if(count==len-cha){
cao=cnt_next;
}
if(!stk.isEmpty()){
ListNode ha=cnt;
ha.next=stk.peek();
list.add(ha);
}
while(!stk.isEmpty()){
ListNode tem=stk.pop();
if(stk.peek()!=null)
tem.next=stk.peek();
else
{
tem.next=null;
ListNode tail=tem;
list.add(tail);
}
}
}
cnt=cnt_next;
}
for(int i=1;i<list.size();i+=2){
if(i+1>=list.size())
break;
else{
ListNode tmp1=list.get(i);
ListNode tmp2=list.get(i+1);
tmp1.next=tmp2;
}
}
ListNode res=list.get(list.size()-1);
res.next=cao;
ListNode nows=list.get(0);
return nows;
}
}