

文章推荐:如何构建安全可靠的 HarmonyOS 应用
文章链接:https://cloud.tencent.com/developer/article/2465737
文章简介:本文深入探讨了 HarmonyOS App 的安全编码规范与最佳实践,感兴趣的同学可以看看!
本题由于没有合适答案为以往遗留问题,最近有时间将以往遗留问题一一完善。
我们社区陆续会将顾毅(Netflix 增长黑客,《iOS 面试之道》作者,ACE 职业健身教练。)的 Swift 算法题题解整理为文字版以方便大家学习与阅读。
不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。
难度水平:困难
本文讨论了如何在 Swift 中实现对链表的深拷贝,特别是包含随机指针(random)的链表的深拷贝问题。深拷贝要求新链表中的节点完全独立于原链表,但在值、next 和 random 指针的结构上与原链表一致。通过两次遍历链表,并利用字典(Dictionary)存储节点映射关系,本文提供了一种高效且清晰的解决方案。具体实现代码包括节点定义、链表复制逻辑以及测试用例。
给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。
构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。**复制链表中的指针都不应指向原链表中的节点 **。
例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。
返回复制链表的头节点。
用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
val:一个表示 Node.val 的整数。random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。你的代码 只 接受原链表的头节点 head 作为传入参数。
示例 1:

输入:head = 7,null,13,0,11,4,10,2,1,0
输出:7,null,13,0,11,4,10,2,1,0
示例 2:

输入:head = 1,1,2,1
输出:1,1,2,1
示例 3:

输入:head = 3,null,3,0,3,null
输出:3,null,3,0,3,null
提示:
0 <= n <= 1000-10^4 <= Node.val <= 10^4Node.random 为 null 或指向链表中的节点。在 Swift 中,可以通过字典来存储原链表节点与复制链表节点的映射关系,最终实现深拷贝。以下是实现代码:
class Node {
var val: Int
var next: Node?
var random: Node?
init(_ val: Int) {
self.val = val
self.next = nil
self.random = nil
}
}
func copyRandomList(_ head: Node?) -> Node? {
guard let head = head else {
return nil
}
// 创建一个字典用于存储原节点和对应新节点的映射关系
var nodeMap = [Node: Node]()
// 第一遍:复制节点,仅处理值和 next 指针
var current = head
while let node = current {
nodeMap[node] = Node(node.val)
current = node.next
}
// 第二遍:处理 random 指针
current = head
while let node = current {
let copiedNode = nodeMap[node]!
copiedNode.next = node.next != nil ? nodeMap[node.next!] : nil
copiedNode.random = node.random != nil ? nodeMap[node.random!] : nil
current = node.next
}
return nodeMap[head]
}nodeMap 将原链表中的每个节点映射到一个新创建的节点,只处理节点的值 (val) 和 next。nodeMap,为每个新节点设置 random 指针。next 和 random 的引用都指向新链表中的节点。假设链表为 [[7, null], [13, 0], [11, 4], [10, 2], [1, 0]]:
let node1 = Node(7)
let node2 = Node(13)
let node3 = Node(11)
let node4 = Node(10)
let node5 = Node(1)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node5
node2.random = node1
node3.random = node5
node4.random = node3
node5.random = node1
if let newHead = copyRandomList(node1) {
var current: Node? = newHead
while let node = current {
print("Value: \(node.val), Random Value: \(node.random?.val ?? -1)")
current = node.next
}
}Value: 7, Random Value: -1
Value: 13, Random Value: 7
Value: 11, Random Value: 1
Value: 10, Random Value: 11
Value: 1, Random Value: 7
这表明新链表已正确复制了值及指针结构。
点击前往 LeetCode 练习
next 和 random 指针。next 和 random 指针的链接。此算法适用于复杂链表操作及相关问题的扩展,并为学习和使用 Swift 提供了一个实践案例。
我们是由 Swift 爱好者共同维护,我们会分享以 Swift 实战、SwiftUI、Swift 基础为核心的技术内容,也整理收集优秀的学习资料。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。