做算法题最好就是动笔画,能更加深入理解。
【题目】 一种特殊的链表节点类描述如下:
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,请实现一个 函数完成这个链表中所有结构的复制,并返回复制的新链表的头节点。 进阶:不使用额外的数据结构,只用有限几个变量,且在时间复杂度为 O(N)内完成原问题要实现的函数。

方法一:

利用hashMap<Node,Node> ,key值是链表的节点,value是原链表的拷贝(通过new Node来拷贝),遍历一次完成hashMap的初始化,遍历第二次来调整拷贝后的链表的next和rand的指向,辅助空间O(n)

public class CopyList {

	public static class Node{//这里static的意思是Node不能改变,就是不能直接把另一个节点赋值给一个节点,但是它的属性值可以改变
		int value;
		Node next;
		Node rand;
		public Node(int value) {
			this.value=value;
		}
	}
	public static Node copyWithList1(Node head) {
		Node tmp=head;
		HashMap<Node, Node> map=new HashMap<>();
		while(tmp!=null) {
			map.put(tmp, new Node(tmp.value));
			tmp=tmp.next;
		}
		tmp=head;
		while(tmp!=null) {
			map.get(tmp).next=map.get(tmp.next);
			map.get(tmp).rand=map.get(tmp.rand);
			tmp=tmp.next;
		}
		return map.get(head);
		
		
	}
	public static void main(String[] args) {
		Node head=new Node(2);
		head.next=new Node(1);
		head.rand=new Node(1);
		if(copyWithList1(head)==head)
			System.err.println(true);
		else
			System.out.println(false);
	}

}

方法二:

  1. 在原来的链表上做如下改变,但是原来链表的rand指向不变,只是next指向的是节点的拷贝
  2. 分别改变1, 2……3`的rand的指向
  3. 原链表节点和拷贝的链表节点分离
    辅助空间O(1)
    时间复杂度O(N)//N是节点的个数

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

public static Node copyWithList2(Node head) {
		if(head==null)
			return null;
		Node cur=head;
		Node tmp=null;
		//改变链表的next指向,如1指向1`
		while(cur!=null) {
			tmp=cur.next;
			cur.next=new Node(cur.value);
			cur.next.next=tmp;
			cur=tmp;
		}
		//改变拷贝节点的rand指向,如,令1`指向3`
		cur=head;
		while(cur!=null) {
			tmp=cur.next;
			tmp.rand=cur.rand==null?null:cur.rand.next;
			cur=tmp.next;
		}
		//链表分离
		Node res=head.next;
		Node Res=res;
		cur=head;
		while(cur!=null) {
			cur.next=res.next;
			res.next=cur.next==null?null:cur.next.next;
			cur=cur.next;
			res=res.next;
		}
		return Res;
	}

相关文章: