1.题目
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
2.思路
每k个一组 翻转链表
在一个函数中完成,我们首先遍历整个链表,统计出链表的长度,然后如果长度大于等于k,我们开始交换节点,当 k=2 时,每段我们只需要交换一次,当 k=3 时,每段需要交换2此,所以i从1开始循环,注意交换一段后更新 pre 指针,然后 num 自减k,直到 num<k 时循环结束
3.解法1:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
//链表反转
ListNode root = new ListNode(0);
root.next = head;
ListNode res = root;
ListNode tmp = head;
int i = 0;
while(tmp != null){//计算链表长度
i++;
tmp = tmp.next;
}
while(i >= k){
for(int j = 0;j<k-1;j++){
ListNode node = root.next;
root.next = head.next;
head.next = root.next.next;
root.next.next =node;
}
root = head;
head = head.next;
i-=k;
}
return res.next;
}
}
解法2:
一般在处理链表问题时,我们大多时候都会在开头再加一个 dummy node,因为翻转链表时头结点可能会变化,为了记录当前最新的头结点的位置而引入的 dummy node 那么我们加入 dummy node 后的链表变为 -1->1->2->3->4->5,如果k为3的话,我们的目标是将 1,2,3 翻转一下,那么我们需要一些指针,pre 和 next 分别指向要翻转的链表的前后的位置,然后翻转后 pre 的位置更新到如下新的位置:
-1->1->2->3->4->5
| | |
pre cur next
-1->3->2->1->4->5
| | |
cur pre next
以此类推,只要 cur 走过k个节点,那么 next 就是 cur->next,就可以调用翻转函数来进行局部翻转了,注意翻转之后新的 cur 和 pre 的位置都不同了,那么翻转之后,cur 应该更新为 pre->next,而如果不需要翻转的话,cur 更新为 cur->next,代码如下所示:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
//链表反转
/*ListNode root = new ListNode(0);
root.next = head;
ListNode res = root;
ListNode tmp = head;
int i = 0;
while(tmp != null){//计算链表长度
i++;
tmp = tmp.next;
}
while(i >= k){
for(int j = 0;j<k-1;j++){
ListNode node = root.next;
root.next = head.next;
head.next = root.next.next;
root.next.next =node;
}
root = head;
head = head.next;
i-=k;
}
return res.next;*/
if(head==null||k==1)
return head;
ListNode fake = new ListNode(0);
fake.next = head;
ListNode prev = fake;
int i=0;
ListNode p = head;
while(p!=null){
i++;
if(i%k==0){
prev = reverse(prev, p.next);
p = prev.next;
}else{
p = p.next;
}
}
return fake.next;
}
public ListNode reverse(ListNode prev, ListNode next){
ListNode last = prev.next;
ListNode curr = last.next;
while(curr != next){//翻转段内的链表
last.next = curr.next;
curr.next = prev.next;
prev.next = curr;
curr = last.next;
}
return last;
}
}
参考:https://www.cnblogs.com/grandyang/p/4441324.html