图解:K 个一组翻转链表 | LeetCode 级别:困难

本文首发自公众号:承香墨影(ID:cxmyDev),欢迎关注。java

一. 序

链表做为一种基本的数据结构,自己理解起来很简单。它经过指针,将一组零散的内存空间(结点),串联起来,组成一个数据结构。web

在面试的算法题中,常常会碰到链表相关的面试题。虽然链表的结构比较好理解,可是链表的题仍是比较考教代码能力的。一些单链表的题,指针指来指去,很容易就把结点的 next 指针弄丢了,形成链表断裂。面试

链表翻转是一个面试中常常会碰到的题,在以前的文章中,也聊过单链表翻转链表双双翻转,今天再来聊聊它们的「升级版」,以 K 个为一组,翻转链表,同时这也是 LeetCode 的第 25 题。算法

二. K 个一组翻转链表

以 K 个结点为一组,将给定的单链表进行翻转。有点相似以前的链表两两翻转,只是那时的 K = 2。而在这道题中,K 变成一个外部传入的正整数,它是一个可变的值,而且小于或者等于链表的长度。数据结构

这道算法题,会用到以前的知识,既然 K 是可变的,咱们没法估计 K 的大小,可是咱们能够将原始链表,以 K 个结点为一组,执行单链表翻转的逻辑。app

这就要用到以前《单链表翻转》的技巧了,不了解的建议先读读以前的文章。学习

既然须要将原始链表先以 K 个结点分组,再依次执行单链表翻转,在每组字链表翻转以后,还须要将它们再串起来,否者链表不就断裂了么。spa

这就须要使用两个变量 prev 和 end,分别记录子链表的前驱结点,以及子链表的尾结点。有了 end 这个子链表的尾结点,就能够很容易经过 end.next 拿到下一个子链表的头结点。指针

依据这几个结点,就能够完成子链表的翻转,以及保证在子链表翻转后依然能够串起来。code

另外有一个特殊处理的地方,当原始链表以 K 个结点为一组分组时,末尾不满一组的子链表,保持原样不进行翻转。

参考链表两两翻转的思路,为了保证咱们的代码逻辑统一,咱们增长一个虚拟的头结点 dummy,来方便咱们编写代码。

直接上代码,细节都在注释里。

class Solution {
  public ListNode reverseKGroup(ListNode head, int k) {
    // 增长虚拟头结点
    ListNode dummy = new ListNode(0);
    dummy.next = head;

    // 定义 prev 和 end 结点
    ListNode prev = dummy;
    ListNode end = dummy;

    while(end.next != null) {
      // 以 k 个结点为条件,分组子链表
      for (int i = 0; i < k && end != null; i++)
        end = end.next;
      // 不足 K 个时不处理
      if (end == null)
        break;
      // 处理子链表
      ListNode start = prev.next;
      ListNode next = end.next;
      end.next = null;
      // 翻转子链表
      prev.next = reverseList(start);
      // 将子连表先后串起来
      start.next = next;
      prev = start;
      end = prev;
    }
    return dummy.next;
  }

  // 递归完成单链表翻转
  private ListNode reverseList(ListNode head) {
       if (head == null || head.next == null)
      return head;
    ListNode p = reverseList(head.next);
    head.next.next = head;
    head.next = null;
    return p;
  }
}
复制代码

这里单链表的翻转,使用了递归,通常 K 值都不会太大,因此用递归没问题,固然你也能够换成循环实现。对细节不了解的,能够参见《单链表翻转》。

三. 小结时刻

到这里单链表,按 K 分组翻转的具体思路和代码,就介绍清楚了。我这种处理方式可能不是最高效的,可是应该是比较清晰的。

另外在实际面试中,其实不少场景下,都不会直接出 leetcode 上的算法题,都会稍微变种一下,可是你们要学会将复杂问题,转化为简单问题来解决。

到这里,链表翻转的基础题,基本上就说清楚了,包含三个篇文章:

今天就到这里,有任何问题欢迎留言讨论。

本文对你有帮助吗?留言、转发、收藏是最大的支持,谢谢!


公众号后台回复成长『成长』,将会获得我准备的学习资料。

相关文章
相关标签/搜索