题意:需要对链表进行深拷贝,要同时拷贝链表节点的val、next指针和random指针
题解一:
逐个拷贝每个链表节点到当前节点的后面,分三次遍历,每次遍历走两步,最后达到深拷贝的目的
1、第一次遍历原链表,逐个拷贝当前节点的值和next执行,(1->2->3变成1->1'->2->2'->3->3'
)
2、第二次遍历链表,逐个拷贝当前节点的random指针
3、第三次遍历链表,拆分原节点和copy节点
时间复杂度:O(n)
空间复杂度:O(1)
func main() { node1 := &Node{Val: 1} node2 := &Node{Val: 2} node3 := &Node{Val: 3} node1.Next = node2 node2.Next = node3 node1.Random = node3 // Node 1's random points to Node 3 node2.Random = node1 // Node 2's random points to Node 1 node3.Random = nil copyNodeList(node1) } func copyNodeList(head *Node) *Node { if head == nil { return nil } // 1. 新生成copy节点放到原节点的后面,例如1->2->3这样的链表就变成了这样1->1'->2->2'->3->3' var cp *Node = nil for cur := head; cur != nil; cur = cur.Next.Next { // 因为是加上了copy节点,所以每次要移动2步 cp = &Node{Val: cur.Val} // 此时拷贝节点的random指针都指向nil cp.Next = cur.Next cur.Next = cp } // 2. 随机指针的拷贝 for cur := head; cur != nil; cur = cur.Next.Next { if cur.Random != nil { // random指针可能为空 // cur.Next是cur的cp节点,所以cp节点的random指针是cur.random指针的cp节点,也就是cur.Random.Next cur.Next.Random = cur.Random.Next } } // 3. 拆分原节点 和 copy节点 var temp *Node = nil newHead := head.Next for cur := head; cur != nil && cur.Next != nil; { temp = cur.Next // copy节点 cur.Next = temp.Next // 还原旧链表 cur = temp //拆分cp链表 } //PrintList(head) //PrintList(newHead) return newHead } // PrintList 打印随机链表 func PrintList(head *Node) { cur := head var result [][]string for cur != nil { randomVal := "nil" if cur.Random != nil { randomVal = fmt.Sprintf("%d", cur.Random.Val) } result = append(result, []string{fmt.Sprintf("%d", cur.Val), randomVal}) cur = cur.Next } fmt.Println(result) }
解法二:随机链表拷贝的难点,在于如何拷贝next指针和random指针,相当于要同时维护两条链表的关系,解法一是将两个指针的关系分开遍历处理,逐个拷贝;另一种解法就是使用哈希表(map[*node]*node),直接映射旧节点到新节点的拷贝关系,知道当前拷贝节点对应的旧节点状态,就可以通过找旧节点,然后赋值,实现深拷贝
属于空间换时间的解法
时间复杂度:O(n)
空间复杂度:O(n)
func copyRandomList(head *Node) *Node { if head == nil { return nil } // map中存的是(原节点->新节点)的映射关系,此时新节点只有val,指针并没有安排上 nodeMap := make(map[*Node]*Node) for cur := head; cur != nil; cur = cur.Next { nodeMap[cur] = &Node{Val: cur.Val} } // 遍历原链表,根据map关系找到原节点状态,然后对拷贝节点进行赋值 for cur := head; cur != nil; cur = cur.Next { nodeMap[cur].Next = nodeMap[cur.Next] nodeMap[cur].Random = nodeMap[cur.Random] } return nodeMap[head] }
标签:Node,cur,nil,复杂,Next,链表,复制,节点 From: https://www.cnblogs.com/-citywall123/p/18627006