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.
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
Note:
- Only constant extra memory is allowed.
- You may not alter the values in the list's nodes, only nodes itself may be changed.
解题思路:https://leetcode.windliang.cc/leetCode-25-Reverse-Nodes-in-k-Group.html
public ListNode reverseKGroup(ListNode head, int k) { if (head == null) return null; ListNode sub_head = head; ListNode dummy = new ListNode(0); dummy.next = head; ListNode tail = dummy; ListNode toNull = head; while (sub_head != null) { int i = k; //找到子链表的尾部 while (i - 1 > 0) { toNull = toNull.next; if (toNull == null) { return dummy.next; } i--; } ListNode temp = toNull.next; //将子链表断开 toNull.next = null; ListNode new_sub_head = reverse(sub_head); //将倒置后的链表接到 tail 后边 tail.next = new_sub_head; //更新 tail tail = sub_head; //sub_head 由于倒置其实是新链表的尾部 sub_head = temp; toNull = sub_head; //将后边断开的链表接回来 tail.next = sub_head; } return dummy.next; } public ListNode reverse(ListNode head) { ListNode current_head = null; while (head != null) { ListNode next = head.next; head.next = current_head; current_head = head; head = next; } return current_head; }
很好很强大,我很饿
为了将头结点也一般化,我们创建一个 dummy 结点,然后整个过程主要运用三个指针, tail 指针表示已经倒置后的链表的尾部,subhead 指针表示要进行倒置的子链表,toNull 指针为了将子链表从原来链表中取下来。
一个 while 循环,让 toNull 指针走 k - 1 步使其指向子链表的尾部。中间的 if 语句就是判断当前节点数够不够 k 个了,不够的话直接返回结果就可以了。
将子链表指向 null ,脱离出来。并且用 temp 保存下一个结点的位置。
然后调用倒置函数,将子链表倒置。
接下来四步分别是,新链表接到 tail(注意下边的图 tail 是更新后的位置,之前 tail 在 dummy 的位置) 的后边;更新 tail 到新链表的尾部,也就是之前的 subhead (下图 subhead 也是更新后的位置,之前的位置参见上边的图);sub_head 更新到 temp 的位置;toNull 到 sub_head 的位置;然后将新的尾部 tail 把之前断开的链表连起来,接到 sub_head 上。
整理下其实就是下边的样子
和初始的时候(下边的图)对比一下,发现 tail,subhead 和 toNull 三个指针已经就位,可以愉快的重复上边的步骤了。
public class Solution { public ListNode reverseKGroup(ListNode head, int k) { if (k <= 1) return head; int T = GetLength(head) / k; ListNode dummy = new ListNode(0), cur = head, ins = dummy; dummy.next = head; while ((T--) != 0) { for (int i = 0; i < k - 1; ++i) { ListNode move = cur.next; cur.next = move.next; move.next = ins.next; ins.next = move; } ins = cur; cur = cur.next; } return dummy.next; } public int GetLength(ListNode head) { int length = 0; while (head != null) { head = head.next; length++; } return length; } }
Much better、
*/ public class Solution { public ListNode reverseKGroup(ListNode head, int k) { if (k <= 1) return head; int length = 0; ListNode d = head; while(d != null){ length++; d = d.next; } int T = length / k; ListNode dummy = new ListNode(0), cur = head, prev = dummy; dummy.next = head; while ((T--) != 0) { for (int i = 0; i < k - 1; ++i) { ListNode move = cur.next; cur.next = move.next; move.next = prev.next; prev.next = move; } prev = cur; cur = cur.next; } return dummy.next; } }