leetcode-25. K 个一组翻转链表
题目:
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
我的想法是 他是每k个结点进行一次翻转,那么将链表分为若干个k个结点的子链表,将每个子链表取下,将该子链表的头结点放进翻转函数进行翻转,再将翻转后的子链表进行连接。
1.链表的翻转函数
public ListNode fanzhuan(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode n1, n2, n3;
n1 = head;
n2 = n1.next;
n3 = n2.next;
n1.next = null;
while (n2 != null) {
n2.next = n1;
n1 = n2;
n2 = n3;
if (n3 != null) {
n3 = n3.next;
}
}
return n1;
}
2.划分成k长的子链表,然后进行翻转,连接
根据题意k一定是小于等于链表长度,说明只可能出现最后剩余的链表长度小于k,此时则不需要翻转了,直接return新链表的头结点
用pre记录当前翻转后的结点的前一个结点,
用next_h记录下一段子链表的头结点
//将链表分成几段k长的子链表
ListNode pre, h, r, next_h;
pre = null;
h = head;
r = h;
int i;
while (r != null) {
i = 1;
while (i < k && r != null) { //可能出现当前链表节点数小于k
r = r.next;
i++;
}
//此时当前链表节点数小于k不需要翻转
if (r == null) {
pre.next = h;
break;
} else {
next_h = r.next;
r.next = null;
}
if (h == head) {
head = fanzhuan(h);
} else {
pre.next = fanzhuan(h);
}
pre = h;
h = next_h;
r = h;
}
return head;
}
总结
①链表的翻转要熟悉
②将链表分成子链表后,翻转完成后需要重新链回到已经翻转完成的子链表后。然后进行下一段子链表的翻转,为了避免链表断了,需要有指针记录上一段链表的尾结点和下一段链表的头结点。