k个节点的组内逆序调整

package com.demo.algorithm.code04链表;

/**
 * k个节点的组内逆序调整
 *
 * 把一个链表分成 多组,每组K个节点,每组组内链表反转,最后一组若不够k个节点,则不调整
 * 例如: a->b->c->d->e->f->g->h ,假如 k =3 ,则调整后的链表 为:c->b->a->f->e->d->g->h
 */
public class Code04_ReverseNodeInKGroup {

    public class ListNode{
        int val;
        ListNode next;
    }

    //找到组内最后一个节点
    //组内链表反转
    //入参 原链表的头节点,和整型数字K
    /**
     * 思路:
     * step1:定义一个函数getGroupEnd(start,k) ,功能: 找到该组的尾end;
     * step2:定义一个函数reverse(start,end),功能:反转该组,注意反转前,先记录该组尾的next,用于 反转后 新的尾指向该节点
     * 注意:1.第一组反转后的头(即第一组原来的尾)就是整个新链表的头,要提前记录下。
     *       2.第一组的反转要单独写出来,不能写在循环里,因为要记录新链表的头
     *      3.反转前要先判断 step1 得到的 end 是否为null ,不为空说明能凑齐一组,则开始反转,否则不操作
     * step3: 1.先调用getGroupEnd(start,k) 找到 尾end;2.判断end是否为空;3.end!=null,再调用reverse(start,end) 反转,
     * @param head
     * @param k
     * @return
     */
    public ListNode reverseKGroup(ListNode head,int k){
        ListNode end = getGroupEnd(head,k);
        //如果end == null ,说明凑不齐一组,则不调整
        if (end == null){
            return head;
        }
        ListNode star = head;
        //第一组能凑齐,则第一组反转后的头就是整个链表反转后的头
        head = end;
        reverse(star,end); //第一组反转完成 ,c->b->a->d->e->f->g->h
        ListNode curEnd = star; //记录该组的尾,以便 后面的组如果反转,就修改 这个尾指向 后面组反转后的头
        //如果后面还能凑成组
        while (curEnd.next != null ){
            star = curEnd.next;
            end = getGroupEnd(star,k);
            if (end == null){ //如果end == null ,说明凑不齐一组,则不调整
                return head;
            }
            reverse(star,end); //第二组反转完成 ,c->b->a->d  f->e->d->g->h
            curEnd.next = end; //让上一组的尾指向 这组反转后的 新头
            curEnd = star; //记录该组的尾
        }
        return head;

    }

    //得到小组内的最后一个节点
    public ListNode getGroupEnd(ListNode start,int k){
        while (--k > 0 && start!= null){
            start = start.next;
        }
        return start;
    }

    //组内链表反转,不需要返回头(因为第一组 反转后的头 是整个新链表的头,进这个方法前已经得到了,其他的组 调这个方法只是反转)
    public void reverse(ListNode star,ListNode end){
        ListNode pre = null;
        ListNode next = null;
        end = end.next;//记录下一组节点的头,以便 这组 反转完后 ,将这组反转前的头(即反转后的尾)指向 下个节点的头
        ListNode oldHead = star; //star暂存下反转前的组内链表的头,以便 反转完后,让原组内链表的头指向 下一组链表的头
        while (star != end){
            next = star.next;
            star.next = pre;
            pre = star;
            star = next;
        }
        oldHead.next = end;
    }
}

你可能感兴趣的:(链表,数据结构,算法)