前言
首先得区分笔试于面试,笔试的话就不需要考虑空间复杂度,面试需要考虑空间复杂度
一、要求是什么?
现有一种链表,它的节点,不仅仅是有next指针,还有random指针。随机指向链表中的一个节点,也可以为空。现在要将这个链表拷贝一份出来
二、区分场景
1.用哈希表
1.1思路
- 很简单,用哈希表就可以非常简单的复制成功
- 哈希表对应的是老节点和新链表的对应节点
- 用老节点查询老链表中的下一个节点和随机节点
- 再用这个节点的哈希表值链接查询到底节点的哈希值
- 这就直接做好了
1.2代码
代码如下:
public static Node copyListWithRand1(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);
}
2.不用哈希表
1.1思路
- 不用哈希表,我们可以在原链表上进行操作
- 首先将原链表的每一个节点,后面加入一个相同的节点
- 然后遍历一遍链表,每到一个节点,就查找它的random,并找到random后面的节点,将它的后面一个节点连到random后面一个节点上
- 如果为空就不需要连直接赋值为空
- 再重新定义一个节点(头)将那些原链表中新加的,每一个节点后面的一个节点,从头到尾串联起来
- 注意要将原链表复原
1.2代码
代码如下:
public static Node copyListWithRand2(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;
}
总结
这里就体现出哈希表的牛掰之处