leetcode hard模式专杀之25 Reverse Nodes in k-Group

44 篇文章 0 订阅
35 篇文章 0 订阅

这段时间出去面试发现自己做算法题的熟练度还是太不够,继续集训一下,专做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;
    }
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值