Quistion
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明:
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
Ideas
定义:
1 2
| total -> 总节点数 k -> 每组节点书
|
可以把整个链表的翻转拆分成: total % k 个子链表翻转
翻转完成子链表后,原来的head
变成tail
,原来的tail
变成了head
在进行翻转之前通过两个指针分别标记下一个子链表的head
和上一个子链表的tail
:
prev -> [a -> b -> c] -> nextHead
只需要:
将prev.next
指向新的head
,在让prev
自己本身指向tail
将head
指向nextHead
,重新findTail()
就可以翻转每一个子链表
Answer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| class Solution { public ListNode reverseKGroup(ListNode head, int k) { if(k == 1) { return head; }
ListNode tail = findTail(head, k-1); if(tail == null) { return head; }
ListNode start = new ListNode(0, head); ListNode prev = start;
while(tail != null) { ListNode nextHead = tail.next; ListNode[] res = reverse(head, tail, k); prev.next = res[0]; tail = res[1]; tail.next = nextHead; head = nextHead; prev = tail; tail = findTail(head, k-1); }
return start.next; }
public ListNode[] reverse(ListNode head, ListNode tail, int k) { ListNode newHead = tail; ListNode newTail = head;
ListNode x = head; ListNode y = x.next; ListNode z = y.next; int re = k-1;
while(re > 0) { y.next = x;
x = y; y = z; if(z != null) { z = z.next; } re--; } return new ListNode[]{newHead, newTail}; }
public ListNode findTail(ListNode head, int remain) { while(remain > 0) { if(head == null) { return head; } head = head.next; remain--; }
return head; } }
|
执行结果:
通过
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:38.5 MB, 在所有 Java 提交中击败了92.14%的用户