力扣链表高频题:两两交换节点 + K个一组翻转链表(保姆级思路+满分代码)
链表翻转、节点交换是力扣的高频必考题型也是面试手撕链表的常客。今天一次性攻克两道经典题24. 两两交换链表中的节点和25. K 个一组翻转链表从思路拆解到代码实现一步步讲透新手也能轻松拿捏。这两道题一脉相承两两交换其实就是K2的特殊情况掌握通用解法两道题一起搞定高效刷题不费力24. 两两交换链表中的节点 - 力扣LeetCode题目大意给定一个链表两两交换相邻的节点返回交换后的链表头节点要求不能单纯修改节点的值必须真正执行节点交换操作。解题思路这道题直接操作节点指针即可核心是借助虚拟头节点统一链表头节点和后续节点的处理逻辑避免单独处理头节点的边界情况。解题时定义四个辅助节点分步完成交换虚拟节点作为链表的前驱节点解决头节点交换后丢失的问题临时指针始终指向待交换两个节点的前一个节点用于衔接交换后的节点first、second分别指向当前要交换的第一个和第二个节点tmp保存待交换节点的后继节点防止交换后链表断裂循环判断条件保证后续有两个节点可以交换再执行交换逻辑不足两个节点直接终止循环。满分代码/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val val; } * ListNode(int val, ListNode next) { this.val val; this.next next; } * } */ class Solution { public ListNode swapPairs(ListNode head) { // 定义虚拟头节点统一链表操作逻辑 ListNode current new ListNode(-1); current.next head; // 临时节点始终指向待交换节点的前一个位置 ListNode cu current; // 声明待交换的两个节点以及后继节点 ListNode first; ListNode second; ListNode tmp; // 后续有两个节点才执行交换 while (cu.next ! null cu.next.next ! null) { // 定位两个待交换节点 first cu.next; second cu.next.next; // 保存后继节点防止链表断裂 tmp cu.next.next.next; // 执行节点交换 cu.next second; second.next first; first.next tmp; // 指针后移准备下一轮交换 cu first; } // 返回新的链表头 return current.next; } }25. K 个一组翻转链表 - 力扣LeetCode题目大意给你链表的头节点 head每 k 个节点一组进行翻转返回修改后的链表。k 是正整数它的值小于或等于链表的长度如果节点总数不足 k 个保持原有节点顺序不变同样要求只能操作节点指针不可修改节点值。解题思路这道题是上一题的进阶版也是链表分组翻转的通用解法两两交换本质就是k2的特例掌握这道题的思路同类题都能迎刃而解。虚拟头节点依旧用dummy节点让链表第一个分组的处理逻辑和其他分组完全一致省去边界判断双指针定位用pre和end两个指针配合工作pre始终指向待翻转组的前一个节点负责衔接翻转后的链表end先向前走k步定位到当前组的最后一个节点判断剩余节点是否足够k个不足k个节点直接终止循环保留剩余节点原样局部翻转先断开当前分组与后续链表的连接单独翻转该组再将翻转后的分组重新接回原链表指针复位更新pre和end指针准备下一组的翻转操作满分代码/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val val; } * ListNode(int val, ListNode next) { this.val val; this.next next; } * } */ class Solution { public ListNode reverseKGroup(ListNode head, int k) { // 虚拟头节点统一链表操作 ListNode dump new ListNode(-1); dump.next head; // pre待翻转组的前驱节点end当前组的尾节点 ListNode pre dump; ListNode end dump; while (end.next ! null) { // 向前走k步定位到当前组的末尾 for (int i 0; i k end ! null; i) { end end.next; } // 剩余节点不足k个直接退出保持原样 if (end null) break; // 记录当前组的起始节点以及下一组的起始节点 ListNode start pre.next; ListNode next end.next; // 断开分组方便单独翻转 end.next null; // 翻转当前分组 reverse(start); // 将翻转后的分组拼接回原链表 pre.next end; start.next next; // 指针复位准备下一组翻转 pre start; end start; } return dump.next; } // 单链表翻转的工具方法 public void reverse(ListNode head) { ListNode pre null; ListNode cur head; while (cur ! null) { ListNode tmp cur.next; cur.next pre; pre cur; cur tmp; } } }刷题总结这两道链表题核心都是指针操作虚拟头节点巧用虚拟节点能规避大量边界问题写代码更省心。两两交换固定分组大小为2直接交换相邻节点适合入门练手K个一组翻转通用分组翻转解法先定位再翻转最后衔接链表适用性更强链表题切记不要慌画好节点指针走向一步步拆解逻辑手撕代码完全没难度
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2449397.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!