LeetCode 138:随机链表复制(Copy List with Random Pointer)——思路解析 + 易错点总结
目录一、题目简介二、思考过程三、O(1) 空间解法核心Step1 插入复制节点Step2 复制 random 指针Step3 拆分链表四、完整代码C语言五、学习过程中遇到的关键问题六、实现过程中出现的错误总结七、面试官可能会问的问题八、算法思想总结九、我的学习心得一、题目简介题目Copy List with Random Pointer给定一个链表每个节点包含三个字段valnextrandom其中------ next指向下一个节点 ---- random指向链表中的任意节点或 NULL要求深拷贝整个链表返回复制链表的头节点。深拷贝要求 新链表节点地址必须不同 但结构和 random 关系完全一致---二、思考过程方法一哈希表映射最直观的方法是建立映射old_node - new_node步骤1. 第一遍遍历创建所有新节点2. 用哈希表保存映射关系3. 第二遍连接 next 和 random示意map[old] newnew-next map[old-next]new-random map[old-random]复杂度项目| 复杂度时间复杂度| O(n)空间复杂度| O(n)缺点额外使用哈希表---三、O(1) 空间解法核心关键思想把复制节点插入原链表Step1 插入复制节点原链表A → B → C插入复制节点后A → A → B → B → C → C代码if (head NULL) return NULL; // 插入copy节点 struct Node* cur head; while (cur) { struct Node* copy (struct Node*)malloc(sizeof(struct Node)); copy-val cur-val; copy-next cur-next; cur-next copy; cur copy-next; }---Step2 复制 random 指针此时结构A → A → B → B → C → C如果A.random C则A.random C关键技巧cur-random-next原因原节点 - next - 对应复制节点代码cur head; struct Node* newhead head-next; while (cur) { struct Node* copy cur-next; if (cur-random NULL) { copy-random NULL; } else { copy-random cur-random-next; } cur copy-next; }---Step3 拆分链表当前结构A → A → B → B → C → C需要变成原链表A → B → C复制链表A → B → C代码cur head; while (cur) { struct Node* copy cur-next; cur-next copy-next; if (copy-next) { copy-next copy-next-next; } cur cur-next; }四、完整代码C语言/** * Definition for a Node. * struct Node { * int val; * struct Node *next; * struct Node *random; * }; */ struct Node* copyRandomList(struct Node* head) { if (head NULL) return NULL; // 插入copy节点 struct Node* cur head; while (cur) { struct Node* copy (struct Node*)malloc(sizeof(struct Node)); copy-val cur-val; copy-next cur-next; cur-next copy; cur copy-next; } cur head; struct Node* newhead head-next; while (cur) { struct Node* copy cur-next; if (cur-random NULL) { copy-random NULL; } else { copy-random cur-random-next; } cur copy-next; } // 就是将赋值链表提取出来 cur head; while (cur) { struct Node* copy cur-next; cur-next copy-next; if (copy-next) { copy-next copy-next-next; } cur cur-next; } return newhead; }复杂度项目| 复杂度时间复杂度| O(n)空间复杂度| O(1)---五、学习过程中遇到的关键问题在实现过程中容易出现一些逻辑误区。1 遍历指针和修改指针耦合错误思想循环变量依赖正在修改的指针例如n copy-nextwhile(n)如果 copy-next 在循环中被修改可能导致遍历路径不稳定正确思路遍历指针 和 修改指针 分离例如cur 控制循环copy 负责修改---2 为什么可以直接写 copy-random cur-random-next原因复制节点紧挨原节点原节点 - next - 复制节点所以cur-random-next就是对应的复制节点。这就是本题的核心技巧把映射关系嵌入原链表---六、实现过程中出现的错误总结1 与 混淆错误if (head NULL)这是赋值操作。正确if (head NULL)---2 忘记处理空链表测试数据可能是head []如果直接head-next会出现null pointer runtime error正确if (head NULL)return NULL;---3 random 指针复制错误错误写法copy-random NULL正确copy-random cur-random-next---4 return 写在循环内部错误while (...) {...return newhead}导致循环只执行一次---七、面试官可能会问的问题1 为什么不用哈希表回答哈希表需要 O(n) 空间而本题可以通过在原链表中插入复制节点实现 O(1) 空间---2 为什么 cur-random-next 是复制节点回答因为复制节点紧挨原节点A → A → B → B所以原节点.next 复制节点---3 时间和空间复杂度时间复杂度 O(n)空间复杂度 O(1)---4 如果 random 指向 NULL 怎么办需要特殊处理if (cur-random NULL)copy-random NULL;---八、算法思想总结本题的核心思想把节点映射关系嵌入原数据结构通过A → A → B → B这种结构实现O(1) 空间复制链表这种技巧在很多链表题中都非常常见。---九、我的学习心得在实现链表算法时需要特别注意遍历结构稳定性指针修改顺序边界条件尤其是遍历指针不要依赖被修改的指针否则容易出现隐蔽 bug。通过本题可以深入理解链表结构操作指针关系维护
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2426764.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!