问题:
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
You may not alter the values in the nodes, only nodes itself may be changed.
Only constant memory is allowed.
For 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
问题要求:给定一个链表,以及指定的逆序长度k。
链表中每连续k个节点,都需要进行逆序;
若连续节点的长度小于k个,则不做逆序操作。
这里要求使用内存必须是常量级别。
思路:
对于连续的K个节点,我们定义prev、begin、end和nextBegin这几个指针。
如图所示,含义还是很清晰的,不作赘述。
在开始时,将prev的next变为end。
然后,定义一个move指针,从begin开始移动到end的前一个节点。
于是end的next指向move。
end前移到move的位置。
move又从begin开始,移动到end的前一个节点。
再次进行与上面一样的修改。
直到,end移动到begin的后面。
此时,将end的next修改为begin。
begin的next修改为nextBegin,begin将作为后续连续K个节点的Prev。
以上方法并不是最快的,但占用的内存是常数级的(只用到了引用),满足要求。
当然,实际上我这里从最后开始逆着修改next,比较耗时。
从前往后修改也是可以的,只用一个引用保存下一个要修改的节点即可。
代码示例:
1、逆着修改next
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/
public class Solution {public ListNode reverseKGroup(ListNode head, int k) {if (head &#61;&#61; null || k <&#61; 1) {return head;}ListNode temp &#61; head;int len &#61; 0;//先判断长度够不够while (temp !&#61; null) {&#43;&#43;len;if (len &#61;&#61; k) {break;}temp &#61; temp.next;}if (len !&#61; k) {return head;}//初始时prev为nullListNode prev &#61; null;ListNode begin &#61; head;//长度够的话&#xff0c;最终的头为此时的第K个节点head &#61; temp;while (begin !&#61; null) {//每次操作前&#xff0c;记录当前的begin&#xff0c;这是下一次的prevListNode lastBegin &#61; begin;begin &#61; reverseKGroupInternal(prev, begin, k);prev &#61; lastBegin;}return head;}private ListNode reverseKGroupInternal(ListNode prev, ListNode begin, int k) {ListNode temp &#61; begin;ListNode end &#61; null;ListNode nextBegin &#61; null;int len &#61; 0;//同样需要判断此次操作的长度是否满足条件while (temp !&#61; null) {&#43;&#43;len;if (len &#61;&#61; k) {//得到本次操作的end及nextBeginend &#61; temp;nextBegin &#61; end.next;break;}temp &#61; temp.next;}if (len !&#61; k || end &#61;&#61; null) {return null;}//prev的next指向endif (prev !&#61; null) {prev.next &#61; end;}ListNode move;while (begin.next !&#61; end) {//移动move到end的前面move &#61; begin;while (move.next !&#61; end) {move &#61; move.next;}//end的next指向moveend.next &#61; move;//前移endend &#61; move;}//最后时刻&#xff0c;end刚好在begin后面//修改end.next指向beginend.next &#61; begin;//begin.next指向nextBeginbegin.next &#61; nextBegin;return nextBegin;}
}
2、基本逻辑与上面一致&#xff0c;就是顺着改next
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val &#61; x; }* }*/
public class Solution {public ListNode reverseKGroup(ListNode head, int k) {if (head &#61;&#61; null || k <&#61; 1) {return head;}ListNode temp &#61; head;int len &#61; 0;while (temp !&#61; null) {&#43;&#43;len;if (len &#61;&#61; k) {break;}temp &#61; temp.next;}if (len !&#61; k) {return head;}ListNode prev &#61; null;ListNode begin &#61; head;head &#61; temp;while (begin !&#61; null) {ListNode lastBegin &#61; begin;begin &#61; reverseKGroupInternal(prev, begin, k);prev &#61; lastBegin;}return head;}private ListNode reverseKGroupInternal(ListNode prev, ListNode begin, int k) {ListNode temp &#61; begin;ListNode end &#61; null;ListNode nextBegin &#61; null;int len &#61; 0;while (temp !&#61; null) {&#43;&#43;len;if (len &#61;&#61; k) {end &#61; temp;nextBegin &#61; end.next;break;}temp &#61; temp.next;}if (len !&#61; k || end &#61;&#61; null) {return null;}if (prev !&#61; null) {prev.next &#61; end;}ListNode first &#61; begin;ListNode second &#61; begin.next;begin.next &#61; nextBegin;//只有下面这部分存在差异while(second !&#61; null && second !&#61; end) {ListNode local &#61; second.next;second.next &#61; first;first &#61; second;second &#61; local;}if (second !&#61; null) {second.next &#61; first;}return nextBegin;}
}
在前文的基础上&#xff0c;可以进一步优化每一段逆转的逻辑&#xff0c;即每一段轮询的同时完成逆转&#xff1a;
class Solution {public ListNode reverseKGroup(ListNode head, int k) {if (head &#61;&#61; null || k <&#61; 1) {return head;}ListNode ret &#61; head;ListNode pre &#61; null;ListNode nextBegin;ListNode begin &#61; head;ListNode end &#61; begin;while (begin !&#61; null) {int count &#61; 1;while(count }