题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),
返回结果为复制后复杂链表的head。
(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
题目分析
题意就是: 复制一个链表, 但链表中还有一个指针域指向链表中的其他节点.
这里用两种方法来解决: `1) 暴力法 2) 哈希表
代码
方法一: 暴力解法
暴力解法的思路: 每次从链表中找到Random节点, 记录下步数(编号), 再从复制表里走相应步数即为随机指针指向的节点. 为暴力法.
方法二: 哈希表
使用HashMap, 建立主表与复制表之间的联系, 遍历主表, 将随机节点对应的复制表节点作为随机表的random指针指向即可.
/*
public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
*/
import java.util.Map;
import java.util.HashMap;
public class Solution {
public RandomListNode CloneNode1(RandomListNode phead) {
RandomListNode dummy = new RandomListNode(0);
RandomListNode p = phead, q = dummy;
while (p != null) {
RandomListNode r = new RandomListNode(p.label);
q.next = r;
p = p.next;
q = q.next;
}
return dummy.next;
}
// 使用暴力法
public void cloneRandomNode1(RandomListNode phead, RandomListNode pclone) {
RandomListNode p = phead, q = pclone;
while (p != null) {
int count = 0;
RandomListNode t = phead;
while (t != null) {
if (t == p.random) break;
count++;
t = t.next;
}
int now = 0;
t = pclone;
while (now < count) {
t = t.next;
now++;
}
q.random = t;
p = p.next;
q = q.next;
}
}
// 使用HashMap
public Map<RandomListNode, RandomListNode> initCloneMap(RandomListNode phead, RandomListNode pclone) {
RandomListNode p = phead, q = pclone;
Map<RandomListNode, RandomListNode> map = new HashMap<>();
while (p != null) {
map.put(p, q);
p = p.next;
q = q.next;
}
return map;
}
public void cloneRandomNode2(RandomListNode phead, RandomListNode pclone, Map<RandomListNode, RandomListNode> map) {
RandomListNode p = phead, q = pclone;
while (p != null) {
q.random = map.get(p.random);
p = p.next;
q = q.next;
}
}
public RandomListNode Clone(RandomListNode pHead)
{
// 先复制链表结构
RandomListNode pclone = CloneNode1(pHead);
// 后复制随机指针
// 方法一: 暴力查找
//cloneRandomNode1(pHead, pclone);
// 方法二: 使用哈希表
Map<RandomListNode, RandomListNode> map = initCloneMap(pHead, pclone);
cloneRandomNode2(pHead, pclone, map);
return pclone;
}
}