LeetCode 第25题: k个一组翻转链表

1、前言

题目描述

2、思路

首先需要一个反转链表函数,然后在此基础上递归。

需要注意的是,我们是按照 k 去反转,可以使用递归的方法来做,非递归遍历也行。非递归可以参照使用反转链表 m 到 n 之间的数的函数,然后稍加改造。

对于这类题目,最重要的还是用非递归最符合直觉的方法来做。但是非递归就涉及到一个细节问题,就可能就写岔了。所以最重要的要素是把链表反转的头插法先写好,然后从 dummy 出发开始 k 个,然后将链表断开就很好反转了,断开之前记得先记录下个头。断开之后,p 指向 head 的节点,反转后它就变成尾节点。后面不写了,反转记住就这样做。

3、代码

非递归:

class Solution {
    /**
    * 使用反转区间链表的方法,一个区间一个区间的反转,对于最后不足的,直接不反转
    */
    ListNode reverseKGroup(ListNode head, int k) {
        if(head == null || k <= 0){
            return head;
        }

        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode p = dummy, lastHead = dummy;
        while(p != null){
            for(int i = 0; i < k; i++){
                if(p != null){
                    p = p.next;
                }
            }
            if(p == null){
                return dummy.next;
            }
            ListNode temp = p.next;
            p.next = null;
            p = head;
            lastHead.next = reverse(head);
            
            lastHead = p;
            head = temp;
            p.next = head;
        }

        return dummy.next;
    }

    private ListNode reverse(ListNode head){
        if(head == null){
            return head;
        }
        ListNode dummy = new ListNode(-1);
        ListNode p = head;
        while(p != null){
            ListNode temp = p.next;
            ListNode next = dummy.next;
            dummy.next = p;
            p.next = next;
            p = temp;
        }
        return dummy.next;
    }
}

递归:

class Solution {
    ListNode reverseKGroup(ListNode head, int k) {
        if (head == null) return null;
        // 区间 [a, b) 包含 k 个待反转元素
        ListNode a = head, b = head;
        for (int i = 0; i < k; i++) {
            // 不足 k 个,不需要反转,base case
            if (b == null) return head;
            b = b.next;
        }
        // 反转前 k 个元素
        ListNode newHead = reverse(a, b);
        // 递归反转后续链表并连接起来
        a.next = reverseKGroup(b, k);
        return newHead;
    }

    /** 反转区间 [a, b) 的元素,注意是左闭右开 */
    ListNode reverse(ListNode a, ListNode b) {
        ListNode pre = null, cur = a, next = a;
        // while 终止的条件改一下就行了
        while (cur != b) {
            nxt = cur.next;
            cur.next = pre;
            pre = cur;
            cur = nxt;
        }
        // 返回反转后的头结点
        return pre;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值