LeetCode-25-K 个一组翻转链表

题目

来源:LeetCode.

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例 1:

输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]

示例 2:

输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]

示例 3:

输入:head = [1,2,3,4,5], k = 1
输出:[1,2,3,4,5]

示例 4:

输入:head = [1], k = 1
输出:[1]

提示:

  • 列表中节点的数量在范围 s z sz sz
  • 1 < = s z < = 5000 1 <= sz <= 5000 1<=sz<=5000
  • 0 < = N o d e . v a l < = 1000 0 <= Node.val <= 1000 0<=Node.val<=1000
  • 1 < = k < = s z 1 <= k <= sz 1<=k<=sz

接下来看一下解题思路:

思路一:递归:

    每次递归只需要考虑两件事:

  • 组内的链表翻转
  • 如何将每组翻转的结果串联起来
        组内翻转,我们需要知道这次翻转的头部和尾部;
        翻转后头部就变成尾部了,所以将头部 head指向下一次递归返回的结果;
        这样就巧妙的将每组的结果串联起来了
public static ListNode reverseKGroup1(ListNode head, int k) {
   if (head == null || head.next == null || k <= 1) {
       return head;
   }
   // 当前组的尾结点
   ListNode tail = head;

   for (int i = 1; i < k && tail != null; ++i) {
       tail = tail.next;
   }

   if (tail == null) {
       return head;
   }

   // 下一组的头结点
   ListNode next = tail.next;
   // 翻转每个组内的结点
   reverse(head, tail);
   // 连接下一组的头结点
   head.next = reverseKGroup(next, k);

   return tail;
}

/**
* 单组链表翻转
* @param head
* @param tail
*/
private static void reverse(ListNode head, ListNode tail) {
   if (head == tail) {
       return;
   }
   reverse(head.next, tail);
   head.next.next = head;
   head.next = null;
}
思路二:迭代:

    首先,需要计算链表的长度,用来判断需要翻转几次
    对于链表的处理我们一般需要定义三个结点(前驱结点、当前结点、后继结点)
    然后做一个大循环,判断有几组需要翻转;
    再做一个循环,用于改变链表的指向,做组内翻转;
    我们还需要定义一个结点,用于返回翻转后的结果链表;

public static ListNode reverseKGroup(ListNode head, int k) {
    if (head == null || head.next == null || k <= 1) {
        return head;
    }

    // 用于保存翻转后的链表头结点
    ListNode node = new ListNode(-1, head);
    // 计算链表的长度
    int length = 0;
    while (head != null) {
        ++length;
        head = head.next;
    }
    head = node.next;
    // 当前结点的后继结点
    ListNode next = null;
    // 当前结点
    ListNode cur = head;
    // 当前结点的前驱结点,用于连接翻转后的每一组
    ListNode prev = node;
    for (int i = 0; i < length / k; ++i) {
        for (int j = 0; j < k - 1; ++j) {
            next = cur.next;
            cur.next = next.next;
            next.next = prev.next;
            prev.next = next;
        }
        prev = cur;
        cur = prev.next;
    }
    return node.next;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值