leetcode题解-25. Reverse Nodes in k-Group

题目:

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

You may not alter the values in the nodes, only nodes itself may be changed.

Only constant memory is allowed.

For example,
Given this linked list: 1->2->3->4->5

For k = 2, you should return: 2->1->4->3->5

For k = 3, you should return: 3->2->1->4->5

本题是要将原始链表每k各节点分成一组,然后组内翻转,最后一组如果不满k个,则不进行反转,保留原始的顺序,难点在于如何判断最后一组的情况以及两个相邻组转换之后的头和尾要连接在一起,如何解决这个时间差。所以自然而然的想到了递归的方法,这样先解决最后一个k元祖,然后在一个一个向前遍历,每次都把当前k元组排列好才进行下一个,很好的解决了上述两个问题。代码如下所示:

    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode cur = head, next=head;
        int i=0;
        //先判断是否已经到了最后,且是否到k个元素
        while(next != null && i < k){
            next = next.next;
            i++;
        }
        //如果不足k个,则不进行反转,直接返回
        if(i < k)
            return head;
        //如果还没到链表末端,则递归调用处理下一个
        ListNode pre = reverseKGroup(next, k);
        //这里是主要的代码部分,就是实现K远足的反转,pre是上个k元组的头,也是本k元组的尾
        while(k -- > 0){
            next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }

当然我们也可以使用便利的方法来进行求解,思路是每次翻转两个相邻的元素,把原始的头结点一步一步向后移,当翻转完成后将其作为下一个k元组的起始节点,比如:原始链表为12345,k=3

0--1--2--3--4--5
|
pre

0--2--1--3--4--5
|
pre

0--3--2--1--4--5
         |
         pre

代码如下所示:

        public ListNode reverseKGroup(ListNode head, int k) {
            if (k <= 1 || head == null || head.next == null)
                return head;
            ListNode newHead = new ListNode(0);
            newHead.next = head;
            ListNode prev, start, then, tail;
            tail = prev = newHead;
            start = prev.next;
            while (true) {
                // check if there's k nodes left-out
                for (int i = 0; i < k; i++) {
                    tail = tail.next;
                    if (tail == null)
                        return newHead.next;
                }
                // reverse k nodes
                for (int i = 0; i < k - 1; i++) {
                    then = start.next;
                    start.next = then.next;
                    then.next = prev.next;
                    prev.next = then;
                }
                tail = prev = start;
                start = prev.next;
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值