25.K个一组翻转链表

image-20200516162313970

集合

思路

  • 存入集合

  • 在集合中进行翻转

  • 遍历操作后的集合 ,构建新的链表

  • 很明显 过程耗时间空间

代码

/**
     *6ms  7%
     */
    public ListNode reverseKGroup(ListNode head, int k) {
        if(head==null) return null;
        //存入集合
        List<ListNode> nodes=new ArrayList<>();
        while(true){
            if(head==null){
                break;
            }
            nodes.add(head);
            head=head.next;
        }
//        System.out.println(nodes.toString());
        int len=nodes.size();
        int mode=len%k;
        for(int i=0;i<len-mode;i+=k){
            //首尾交换规律
            int index=i+(i+k-1);
            for(int j=i;j<i+k/2;j++){
                ListNode temp=nodes.get(j);
                nodes.set(j,nodes.get(index-j));
                nodes.set(index-j,temp);
            }
        }
        ListNode head2=new ListNode(-1);
        ListNode temp=head2;
        nodes.get(len-1).next=null;//若设置末尾为null 例如[1,2] 翻转后[2,1] 但此时1.next.val=2,构成死循环
        for(ListNode node:nodes){
            temp.next=node;
            temp=temp.next;
        }
//        list(head2.next);
        return head2.next;

    }

  • 使用 进行链表交换

    image-20200516171132576

    代码

        /**
         * 使用栈进行交换
         * 3ms  12%
         */
        public ListNode reverseKGroup2(ListNode head, int k) {
            Stack<ListNode> stack=new Stack<>();
            ListNode dummy=new ListNode(-1);
            ListNode p=dummy;
            while(true){
                int count=0;
                ListNode tmp=head;
                while(tmp!=null&&count<k){
                    stack.add(tmp);
                    tmp=tmp.next;
                    count++;
                }
                if(count!=k){
                    p.next=head;
                    break;
                }
                while(!stack.isEmpty()){
                    p.next=stack.pop();
                    p=p.next;
                }
                p.next=tmp;
                head=tmp;
            }
            return dummy.next;
        }
    
    

头插法

参考原文王小二:图解k个一组翻转链表



图解如下:

代码

   /**
     * 0ms
     */
    public ListNode reverseKGroup3(ListNode head,int k){
        ListNode dummy=new ListNode(-1);
        dummy.next=head;

        ListNode pre=dummy;
        ListNode end=dummy;
        while(end.next!=null){
            for(int i=0;i<k&&end!=null;i++) end=end.next;
            if(end==null) break;
            ListNode start=pre.next;
            ListNode next=end.next;
            end.next=null;
            pre.next=reverse(start);
            start.next=next;
            pre=start;
            end=pre;
        }
        return dummy.next;
    }
    public ListNode reverse(ListNode head){
        ListNode pre=null;
        ListNode cur=head;
        while(cur!=null){
            ListNode next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }

问题

​ 链表操作(交换)与数组操作 有很大区别 ,数组交换主要是值的交换,而链表是整体。同时需妥善处理next指针,稍不注意易造成节点死循环。 例如[1,2] 翻转后[2,1] 若1.next不设置成null,此时1.next.val=2,构成死循环。

原文地址:https://www.cnblogs.com/yh-simon/p/12901374.html