链表--复制含有随机指针节点的链表
一种特殊的链表节点类描述如下:
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>将head节点均保存进去,key是head的结点,value是相应节点复制的新节点
然后遍历Map,将对应的rand结点找出来相连接
public static Node copyRandom1(Node head){ if(head == null || head.next == null) return head; Map<Node, Node> map = new HashMap<>(); Node node = head; while(node != null){ map.put(node, new Node(node.val)); node = node.next; } node = head; while(node != null){ map.get(node).next = node.next; map.get(node).rand = node.rand; node = node.next; } return map.get(head); }
解法二:将next结点先链接在node结点之后,然后将遍历的时候,将node结点的rand作为线索
然后将node.next的rand找到指向,最后再将两个链表分开即可。
public static Node copyRandom2(Node head){ if(head == null || head.next == null) return head; Node node = head; while(node != null){ Node nextNode = node.next; node.next = new Node(node.val); node.next.next = nextNode; node = nextNode; } node = head; while(node != null){ node.next.rand = node.rand; node = node.next.next; } node = head; Node newHead = node.next; while(node != null){ Node nextNode = node.next.next; Node node1 = node.next; node.next = nextNode; node1.next = nextNode != null ? nextNode.next : null; node = nextNode; } return newHead; }