题意:
解题思路:
思路:O(n)
第一步,将新生成的结点放在原结点的后边,即 1 -> 1' -> 2 -> 2' -> NULL。新结点的随机指针指向原结点。
第二步,扫描合成的链表,更新新结点的随机指针为原来指向结点的 next。//$p->next->random = $p->random->next;
第三步,将两个链表分离,恢复原链表,返回新链表的头结点。
PHP代码实现:
/**
* Definition for a Node.
* class Node {
* public $val = null;
* public $next = null;
* public $random = null;
* function __construct($val = 0) {
* $this->val = $val;
* $this->next = null;
* $this->random = null;
* }
* }
*/
class Solution {
/**
* @param Node $head
* @return Node
*/
function copyRandomList($head) {
//复制一个小弟
for ($p = $head; $p; $p = $p->next->next) {
$q = new Node($p->val);
$q->next = $p->next;
$p->next = $q;
}
//复制random指针
for ($p = $head; $p; $p = $p->next->next) {
if ($p->random) {
$p->next->random = $p->random->next;
}
}
//拆分两个链表
$dummy = new Node(-1);
$cur = $dummy;
for ($p = $head; $p; $p = $p->next) {
$q = $p->next;
$cur = $cur->next = $q;
$p->next = $q->next;
}
return $dummy->next;
}
}
GO代码实现:
/**
* Definition for a Node.
* type Node struct {
* Val int
* Next *Node
* Random *Node
* }
*/
func copyRandomList(head *Node) *Node {
if head == nil {
return head
}
// 复制节点,紧挨到到后面
// 1->2->3 ==> 1->1'->2->2'->3->3'
cur := head
for cur != nil {
clone := &Node{Val: cur.Val, Next: cur.Next}
temp := cur.Next
cur.Next = clone
cur = temp
}
// 处理random指针
cur = head
for cur != nil {
if cur.Random != nil {
cur.Next.Random = cur.Random.Next
}
cur = cur.Next.Next
}
// 分离两个链表
cur = head
cloneHead := cur.Next
for cur != nil && cur.Next != nil {
temp := cur.Next
cur.Next = cur.Next.Next
cur = temp
}
// 原始链表头:head 1->2->3
// 克隆的链表头:cloneHead 1'->2'->3'
return cloneHead
}