复杂链表的赋值
题目分析
普通链表的节点定义如下:
// Definition for a Node.
class Node {
int val;
Node next;
public Node(int val) {
this.val = val;
this.next = null;
}
}
本题链表的节点的定义如下
比普通的链表多了一个random
// Definition for a Node.
class Node {
int val;
Node next, random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
就是在复制链表的时候还要带着random
这个时普通链表的复制
class Solution {
public Node copyRandomList(Node head) {
Node cur = head;
Node dum = new Node(0), pre = dum;
while(cur != null) {
Node node = new Node(cur.val); // 复制节点 cur
pre.next = node; // 新链表的 前驱节点 -> 当前节点
// pre.random = "???"; // 新链表的 「 前驱节点 -> 当前节点 」 无法确定
cur = cur.next; // 遍历下一节点
pre = node; // 保存当前新节点
}
return dum.next;
}
}
利用哈希表查表
HashMap 的键值对,构建原来的链表节点和新链表的对应节点的键值对映射关系,然后再遍历next和random引用指向
拼接 + 拆分
也就是构建新的链表为
node1→node1new→node2→node2 new→⋯
因此当node1指向node2的时候node1new也指向node2new,node1的random指向自己的random的时候,那node1new的random也就只想node1.random.next
/*
// Definition for a Node.
class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
*/
class Solution {
public Node copyRandomList(Node head) {
if(head==null) return null;
//首先定义旧链表的头节点
Node cur = head;
//复制各个节点构成拼接链表
while(cur!=null){
Node temp = new Node(cur.val);
//新链表节点的next是当前节点的next
temp.next = cur.next;
//当前节点的next是新节点
cur.next = temp;
//继续便利,下一个节点应该是当前节点的next的next,也就是temp的next
cur = temp.next;
}
//对新拼接的链表设置random指向
cur = head;
while(cur!=null){
if(cur.random!=null){
//下一个节点也就是新节点的随机等于当前旧节点的随机的next
cur.next.random = cur.random.next;
}
cur = cur.next.next;
}
//指向完毕 对链表进行拆分 直接拿头节点的next就是新链表的头节点
cur = head.next;
Node res = head.next;
Node pre = head;
while(cur.next!=null){
pre.next = pre.next.next;
cur.next = cur.next.next;
pre = pre.next;//旧链表
cur = cur.next;//新链表
}
//执行完毕之后,旧链表还差一个尾节点的next的null没加
//因为他本来的next应该是新链表,但是拆开之后就变成null了
pre.next = null;
return res;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。