【算法通关村第二关——K个一组反转】

K个一组反转

主要有两种思路:

  1. 穿针引线法实现分组反转,及直接反转
  2. 头插法实现分组反转,及定义一个虚拟头节点,去分组反转,切换每个组的时候,将头节点也换到对应的每组的上一个节点

穿针引线法

【算法通关村第二关——K个一组反转】_第1张图片
【算法通关村第二关——K个一组反转】_第2张图片

public static ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(0);
        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;
    }

    private static ListNode reverse(ListNode head) {
        ListNode pre = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode next = curr.next;
            curr.next = pre;
            pre = curr;
            curr = next;
        }
        return pre;
    }

头插法

【算法通关村第二关——K个一组反转】_第3张图片

直接上代码,细节已经写在代码注释上,建议读者边画图,边读代码,方便理解:

public static ListNode reverseKGroup2(ListNode head, int k) {
        //定义虚拟头结点
        ListNode dummyNode = new ListNode(0);
        dummyNode.next = head;
        ListNode cur = head;
        int len = 0;
        //先计算出链表的长度
        while(cur != null) {
            len++;
            cur = cur.next;
        }
        //计算出有n组
        int n = len/k;
        ListNode pre = dummyNode;
        cur = head;
        //第一层遍历组
        for(int i=0;i<n;i++) {
            //第二层遍历每个组中的节点并反转
            for(int j=0;j<k-1;j++) {
                //先记录当前节点的下一个节点next
                ListNode next = cur.next;
                //当cur的next指针指向cur的下下个节点,防止节点丢失,不能够继续反转
                cur.next = cur.next.next;
                //将next节点的 指针指向pre的下一个
                next.next = pre.next;
                //pre的next指针指向next
                pre.next = next;
            }
            //分组内的链表反转完后,将pre指针指向下一组的前一个节点
            pre = cur;
            //cur指针向前移动一位
            cur = cur.next;
        }
        return dummyNode.next;
    }

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