K个一组反转(算法通关村第二关黄金挑战)
-
LeetCode25: 给你一个链表,每 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]
1头插法
-
如果虚拟结点理解了,主要思路还是将其分成已经反转、正在反转和未反转三个部分。为了方便循环,我们可以先遍历一遍数组,统计一下元素数量len,确定要分几组n=len/k,然后反转就可以了。
-
//头插法 public LinkListNode reverseKGroup(LinkListNode head, int k){ LinkListNode dummyNode = new LinkListNode(0); dummyNode.next = head; LinkListNode cur = head; int len = 0;//计算链表长度 while(cur != null){ cur = cur.next; len++; } int n = len/k;//计算出共有几组需要反转 LinkListNode prev = dummyNode; cur = prev.next; for(int i = 0; i < n; i++){ for(int j = 0; j < k-1; j++){ LinkListNode next = cur.next; cur.next = next.next; next.next = prev.next; prev.next = next; } prev = cur; cur = cur.next; } return dummyNode.next; }
2穿针引线法
-
分组处理,将其分成已经反转,正在反转和未反转三个部分,同时为处理好头结点,我们新建一个虚拟头结点。之后我们直接遍历,变量pre, start, end, next。
-
//穿针引线法 public LinkListNode reverseKGroup2(LinkListNode head, int k){ LinkListNode dummy = new LinkListNode(0); dummy.next = head; LinkListNode pre = dummy; LinkListNode end = dummy; while(end.next != null){ //找到要处理区间的末尾 for(int i = 0; i < k && end != null; i++){ end = end.next; } if(end == null){ break; } //将要处理的区间裁剪下来 LinkListNode start = pre.next; LinkListNode next = end.next; end.next = null; //执行反转,并缝补回去 pre.next = reverse(start); start.next = next; //调整指针,为下一组做准备 pre = start; end = pre; } return dummy.next; } private LinkListNode reverse(LinkListNode head){ LinkListNode pre = null; LinkListNode curr = head; while(curr != null){ LinkListNode next = curr.next; curr.next = pre; pre = curr; curr = next; } return pre; }