目录
- 题目
- 法一、模拟--迭代
- 法二、递归
题目
- 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
法一、模拟--迭代
- 遍历列表,到达计数k将k个用头插法翻转,注意翻转后连接回整个链表。没有达到k不进行翻转
var reverseKGroup = function(head, k) {// 创建一个虚拟节点,以简化边界条件处理let dummy = new ListNode();dummy.next = head; // 将虚拟节点的next指向原链表的头节点let [start, end] = [dummy, dummy.next]; // start指向虚拟节点,end指向链表的第一个节点let count = 0; // 计数器,用于计数节点// 遍历链表,直到end为nullwhile(end) {count++; // 计数节点数量// 当计数到k的倍数时,表示需要进行翻转if (count % k === 0) {// 翻转start到end之间的链表start = reverseList(start, end.next);end = start.next; // 更新end为翻转后的链表的下一个节点} else {end = end.next; // 移动end指针}}return dummy.next; // 返回翻转后的链表头节点,即dummy.next// 翻转start到end之间的链表function reverseList(start, end) {let [pre, cur] = [start, start.next]; // pre指向start,cur指向start的下一个节点const first = cur; // 记录翻转后的第一个节点// 头插法进行翻转,直到cur等于endwhile(cur !== end) {let next = cur.next; // 记录cur的下一个节点cur.next = pre; // 将cur的next指向pre,实现翻转pre = cur; // 移动pre到curcur = next; // 移动cur到下一个节点}// 将翻转后的子链表连接前后start.next = pre; // 将start的next指向翻转后的第一个节点first.next = cur; // 将翻转后的第一个节点的next指向end(即cur)return first; // first经过翻转应该在子链表最后}
};
法二、递归
var reverseKGroup = function(head, k) {let cur = head;let count = 0;// 求k个待反转元素的首节点和尾节点while(cur != null && count != k){cur = cur.next;count++;}// 足够k个节点,去反转if(count == k){// 递归链接后续k个反转的链表头节点cur = reverseKGroup(cur,k);while(count != 0){count--;// 反转链表let tmp = head.next;head.next = cur;cur = head;head = tmp;}head = cur;}return head;
};