这段时间出去面试发现自己做算法题的熟练度还是太不够,继续集训一下,专做leetcode的hard模式,这道题我估计如果在面试时碰到,八成要死,这种题属于逻辑想出来不算复杂,但是写出代码来坑巨多的题目,估计这也是这种题被放在hard模式的原因吧。
面试的时候如果出这种题,未必是考你逻辑,而是考你思维严密度,这题的happy flow我很快就做出来了,但是真正通过leetcode OJ却是在改了三五次以后,修改太多次说明思维不够缜密,很容易被面试官笔试。
anyway,说思路吧:前段时间正好写了一个链表逆置的方法, 所以就直接拿来用了,逆置一个完整的链表有两种方法,第一是两个指针一个指向i,一个指向i+1,然后逐步设置next, 第二种方法是是一个个把头节点摘下来,放到另一个链表中,每次都往新链表头插入,这样摘-插完成后新链表就是逆序了。
这道题是每隔k个逆序,最后不足k的顺序。例如1,2,3,4,5以3为单位,则变成3,2,1,4,5, 所以可以利用第一种逆序方法,摘-插,第一段变成3,2,1,然后剩下的4,5保留,继续插入,说起来是不是很简单?跟没说一样,没错,思路就是这样,具体代码如下, 我解释一下第一个revert函数是用来翻转最后一段5,4的,因为我这里会用循环来统一处理每个segment, 所以做完后每段都是逆序的,但是我需要最后一段顺序,所以就用了这个函数。result变量用来保存最终结果,每次把segment或者segment的逆序加入result, 而加入的方法就是把链表尾的next设置为新segment的头即可,为了不用每次都从头去找这个尾巴,就用了个pre变量来记录,而post变量是用来辅助寻找pre变量的,这两个变量什么时候更新本身也是个大坑。另外还有个坑是k=1时候的边界条件,也需要注意。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
private static ListNode revert(ListNode result){
if(result == null){
return result;
}
ListNode inode = result;
if(inode.next==null){
//single node
return result;
}
ListNode jnode=inode.next;
inode.next = null;
while(true){
ListNode tmpNode = jnode.next;
if(tmpNode == null){
jnode.next = inode;
result = jnode;
return result;
}
jnode.next = inode;
inode = jnode;
jnode=tmpNode;
}
}
public ListNode reverseKGroup(ListNode head, int k) {
int index = 0;
ListNode pre = null;
ListNode post = null;
ListNode result = null;
ListNode segment = null;
ListNode tmpNext = null;
ListNode p = head;
while(p!=null){
tmpNext = p.next;
if(segment == null){
p.next = null;
segment = p;
post = p;
if((index+1)%k==0){
if(result == null){
result = segment;
}
if(pre!=null){
pre.next = segment;
}
pre = post;
segment = null;
}
}else{
if((index+1)%k==0){
p.next = segment;
segment = p;
if(pre!=null){
pre.next = segment;
}
pre = post;
if(result == null){
result = segment;
}
segment = null;
}else{
p.next = segment;
segment = p;
}
}
p=tmpNext;
index++;
}
if(segment!=null){
if(result == null){
result = revert(segment);
}
if(pre!=null){
pre.next = revert(segment);
}
}
return result;
}
}