赞
踩
给你一个链表,每 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]
思路: 将链表根据 k 的值进行分组, 再分别对每一组进行反转。
代码实现:
/** * 头插法 * * @param head * @param k * @return */ public static ListNode reverseKGroup2(ListNode head, int k) { ListNode dummyNode = new ListNode(-1); dummyNode.next = head; ListNode curr = head; // 计算链表长度 int len = 0; while (curr != null) { len++; curr = curr.next; } // 根据 k的值进行分组 int n = len / k; ListNode pre = dummyNode; curr = head; // 分组进行反转 for (int i = 0; i < n; i++) { for (int j = 0; j < k - 1; j++) { ListNode next = curr.next; curr.next = curr.next.next; next.next = pre.next; pre.next = next; } // 准备进入下一组反转 pre = curr; curr = curr.next; } return dummyNode.next; }
思路: 将链表分组处理, 将其分为已经反转、正在反转、未反转三个部分。遍历链表, 根据 k 的值找到四个关键位置, 分别代表已经反转部分的尾结点、正在反转部分的头节点、正在反转部分的尾结点以及未反转部分的头节点, 使用变量 pre、start、end和next标记。
对待反转的部分进行反转:
调整指针位置, 进行下一组反转:
代码实现:
/** * 穿针引线法 * * @param head * @param k * @return */ public static ListNode reverseKGroup(ListNode head, int k) { ListNode dummyNode = new ListNode(-1); dummyNode.next = head; ListNode pre = dummyNode; ListNode end = dummyNode; while (end.next != null) { // 先找到待反转链表部分的尾节点 for (int i = 0; i < k && end != null; i++) { end = end.next; } if (end == null) { // 当最后一组待反转链表长度小于k, 不满足要求时, 退出循环 break; } // 待反转链表部分的头节点 ListNode start = pre.next; // 未反转 (下一组) 部分链表头节点 ListNode next = end.next; end.next = null; pre.next = reverse(start); start.next = next; pre = start; end = pre; } return dummyNode.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; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。