JAVA程序设计:复制带随机指针的链表(LeetCode:138)

给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。

要求返回这个链表的深拷贝。 

 

示例:

输入:
{"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}

解释:
节点 1 的值是 1,它的下一个指针和随机指针都指向节点 2 。
节点 2 的值是 2,它的下一个指针指向 null,随机指针指向它自己。
 

提示:

你必须返回给定头的拷贝作为对克隆列表的引用。

 

方法一:回朔。 如果没有随机指针,呢就是一条链进行深拷贝即可,但是因为随机指针的存在,链表就成为了一个有向图,因此我们需要按照图的遍历方式进行深拷贝,因为随机指针的随机性,使得这个图可能存在环,因此我们需要标记我们已经遍历过的节点,以防形成死循环。

class Node {
    public int val;
    public Node next;
    public Node random;

    public Node() {}

    public Node(int _val,Node _next,Node _random) {
        val = _val;
        next = _next;
        random = _random;
    }
};

class Solution {
	
	HashMap<Node,Node> visitedNode=new HashMap<>();
	
    public Node copyRandomList(Node head) {
        
    	if(head==null)
    		return null;
    	
    	if(visitedNode.containsKey(head))
    		return visitedNode.get(head);
    	
    	Node node=new Node(head.val,null,null);
    	
    	visitedNode.put(head, node);
    	
    	node.next=copyRandomList(head.next);
    	node.random=copyRandomList(head.random);
    	
    	return node;
    }
}

方法二:迭代(O(n)的空间复杂度)

class Node {
    public int val;
    public Node next;
    public Node random;

    public Node() {}

    public Node(int _val,Node _next,Node _random) {
        val = _val;
        next = _next;
        random = _random;
    }
};

class Solution {
	
	HashMap<Node,Node> visitedNode=new HashMap<>();
	
    public Node copyRandomList(Node head) {
        
    	if(head==null)
    		return null;
    	
    	Node oldnode=head;
    	Node newnode=new Node(oldnode.val,null,null);
    	visitedNode.put(oldnode, newnode);
    	
    	while(oldnode!=null)
    	{
    		newnode.random=getCloneNode(oldnode.random);
    		newnode.next=getCloneNode(oldnode.next);
    		
    		oldnode=oldnode.next;
    		newnode=newnode.next;
    	}
    	return visitedNode.get(head);
    }
    
    private Node getCloneNode(Node node)
    {
    	if(node==null)
    		return null;
    	
    	if(visitedNode.containsKey(node))
    		return visitedNode.get(node);
    	else
    	{
    		visitedNode.put(node, new Node(node.val,null,null));
    		return visitedNode.get(node);
    	}
    }
}

方法三:迭代(O(1)的空间复杂度)

方法参考题解:138题解的方法三

class Solution {
	
	HashMap<Node,Node> visitedNode=new HashMap<>();
	
    public Node copyRandomList(Node head) {
        
    	if(head==null)
    		return null;
    	
    	Node ptr=head;
    	
    	while(ptr!=null)
    	{
    		Node newnode=new Node(ptr.val,null,null);
    		
    		newnode.next=ptr.next;
    		ptr.next=newnode;
    		ptr=newnode.next;
    		
    	}
    	
    	ptr=head;
    	while(ptr!=null)
    	{
    		ptr.next.random=(ptr.random!=null)?ptr.random.next:null;
    		ptr=ptr.next.next;
    	}
    	
    	Node ptr_old_list=head;
    	Node ptr_new_list=head.next;
    	Node head_old=head.next;
    	while(ptr_old_list!=null)
    	{
    		ptr_old_list.next=ptr_old_list.next.next;
    		ptr_new_list.next=ptr_new_list.next!=null?ptr_new_list.next.next:null;
    		ptr_old_list=ptr_old_list.next;
    		ptr_new_list=ptr_new_list.next;
    	}
    	
    	return head_old;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值