如何复制一个含有随机指针节点的链表

复制含有随机指针节点的链表

一种特殊的链表节点类描述如下:

public class Node {
	public int value;
	public Node next;
	public Node rand;
	public Node(int data) {
		this.value = data;
	}
}

Node 类中的 value 是节点值,next 指针和正常单链表中 next 指针的意义一样,都指向下一个节点,rand 指针是 Node
类中新增的指针,这个指针可能指向链表中的任意一个节点,也可能指向 null。
给定一个由 Node 节点类型组成的无环单链表的头节点 head,请实现一个函数完成这个链表中所有结构的复制,并返
回复制的新链表的头节点。例如:链表 1->2->3->null,假设 1 的 rand 指针指向 3,2 的 rand 指针指向 null,3
的 rand 指针指向 1。复制后的链表应该也是这种结构,比如,1->2->3->null,1 的 rand 指针指向 3,2 的 rand
指针指向 null,3 的 rand 指针指向 1,最后返回 1。
时间复杂度为 O(N),额外空间复杂度 O(1)


思路:两种实现办法,一种是使用额外空间,建立一个哈希表,用于存储原链表节点与对应的新建链表节点的对应,方法是首先遍历一遍原链表,可以将新建链表每个节点的next指针按照原链表的连接顺序连接,即哈希表中的对应关系是:1->1',2->2',3->3',1'.next->2'.next->3'.next->null,再遍历第二次原链表,根据原链表的rand指针和哈希表中原链表与新链表每个节点的对应关系,将新链表中每个节点的rand指针按照原链表中每个节点的rand指向顺序连接,即可实现,即1'.rand->3'.rand,2'.rand->null,3'.rand->1'。第二种办法,将原链表的每个节点新建并用原链表中每个节点的next指针连接,即1->1'->2->2'->3->3'->null,之后遍历原链表的每个节点的rand指针,即可利用原链表的每个节点的next指向新链表的拷贝节点,对新链表的每个节点的rand指针进行赋值,即可实现。

public static class Node{
	public int value;
	public Node next;
	public Node rand;
	public Node(int data){
		this.value = data;
	}
}

public static Node copyListWithRand_1(Node head){
	HashMap<Node, Node> map = new HashMap<Node,Node>();
	Node cur = head;
	while(cur != null){
		map.put(cur, new Node(cur.value));
		cur = cur.next;
	}
	cur = head;
	while(cur != null){
		map.get(cur).next = map.get(cur.next);
		map.get(cur).rand = map.get(cur.rand);
		cur = cur.next;
	}
	return map.get(head);
}
public static Node copyListWithRand_2(Node head){
	if(head == null){
		return null;
	}
	Node cur = head;
	Node next = null;
	while(cur != null){
		next = cur.next;
		cur.next = new Node(cur.value);
		cur.next.next = next;
		cur = next;
	}
	cur = head;
	Node curCopy = null;
	while(cur != null){
		next = cur.next.next;
		curCopy = cur.next;
		curCopy.rand = cur.rand != null ? cur.rand.next : null;
		cur = next;
	}
	Node res = head.next;
	cur = head;
	while(cur != null){
		next = cur.next.next;
		curCopy = cur.next;
		cur.next = next;
		curCopy.next = next != null ? next.next : null;
		cur = next;
	}
	return res;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值