足球网站怎么做的,三河市建设厅公示网站,wordpress 去掉页头,平面设计一般有哪些软件目录
题目
方法1#xff1a;错误的方法#xff08;初尝试#xff09;
方法2#xff1a;复制、拆开
方法3#xff1a;哈希表
总结 题目
请实现 copyRandomList 函数#xff0c;复制一个复杂链表。在复杂链表中#xff0c;每个节点除了有一个 next 指针指向下一个节…目录
题目
方法1错误的方法初尝试
方法2复制、拆开
方法3哈希表
总结 题目
请实现 copyRandomList 函数复制一个复杂链表。在复杂链表中每个节点除了有一个 next 指针指向下一个节点还有一个 random 指针指向链表中的任意节点或者 null。 题目地址剑指 Offer 35. 复杂链表的复制 - 力扣LeetCode
或同题138. 复制带随机指针的链表 - 力扣LeetCode
方法1错误的方法初尝试
思路
1.先通过递归 创建新链表每个节点的val 和 next 与旧的链表对应关系相同
2.再通过 原链表中每个节点的random的val 来找到新链表中每个节点的random的指向
这种方法是错误的方法可以直接去看后面的方法只是作者刚开始的尝试错误的原因在于每个节点的val不是唯一的这样的话你第2步用val来复制每个节点的random是不可以的有些示例会过不去。
例如
输入head [[7,null],[13,0],[11,4],[10,2],[1,0]] 那么第1步的结果是newNode [[7,null],[13,null],[11,null],[10,null],[1,null]] 然后 第2步就是对每个节点的 random进行指向。
代码
class Solution {public Node copyRandomList(Node head) {//复制节点的val、nextNode newNode copy(head);Node p1 head;Node p2 newNode;//复制节点的 randomwhile (p1 ! null) {if (p1.random ! null) {int val p1.random.val;p2.random findNode(val,newNode);}p1 p1.next;p2 p2.next;}return newNode;}/*** 复制 Node 的 val 和 next*/Node copy(Node oldNode) {if (oldNode null) return null;Node newNode new Node(oldNode.val);newNode.next copy(oldNode.next);return newNode;}/*** 找到某个节点他属于head并且val 是 val*/Node findNode(int val,Node head){if (head null)return null;Node p head;while (p!null){if (p.val val)return p;p p.next;}return null;}
}方法2复制、拆开 思路来自 作者王尼玛链接https://leetcode.cn/problems/copy-list-with-random-pointer/solutions/295083/liang-chong-shi-xian-tu-jie-138-fu-zhi-dai-sui-ji-/来源力扣LeetCode著作权归作者所有。商业转载请联系作者获得授权非商业转载请注明出处。 第一步根据遍历到的原节点创建对应的新节点每个新创建的节点是在原节点后面比如下图中原节点1不再指向原原节点2而是指向新节点1 第二步是最关键的一步用来设置新链表的随机指针 上图中我们可以观察到这么一个规律
原节点1的随机指针指向原节点3新节点1的随机指针指向的是原节点3的next 原节点3的随机指针指向原节点2新节点3的随机指针指向的是原节点2的next 也就是原节点i的随机指针(如果有的话)指向的是原节点j 那么新节点i的随机指针指向的是原节点j的next
第三步就简单了只要将两个链表分离开再返回新链表就可以了 代码 class Solution {public Node copyRandomList(Node head) {if(headnull) {return null;}Node p head;//第一步在每个原节点后面创建一个新节点//1-1-2-2-3-3while(p!null) {Node newNode new Node(p.val);newNode.next p.next;p.next newNode;p newNode.next;}p head;//第二步设置新节点的随机节点while(p!null) {if(p.random!null) {p.next.random p.random.next;}p p.next.next;}//第三步将两个链表分离注意这里是分离不能修改原来的链表Node res new Node(-1);Node oldNode head;Node newNode res;while (oldNode!null){newNode.next oldNode.next;newNode newNode.next;oldNode.next newNode.next;oldNode oldNode.next;}return res.next;}
}
方法3哈希表
思路 思路来自 作者王尼玛链接https://leetcode.cn/problems/copy-list-with-random-pointer/solutions/295083/liang-chong-shi-xian-tu-jie-138-fu-zhi-dai-sui-ji-/来源力扣LeetCode著作权归作者所有。商业转载请联系作者获得授权非商业转载请注明出处。 我们用哈希表来解决这个问题 首先创建一个哈希表再遍历原链表遍历的同时再不断创建新节点 我们将原节点作为key新节点作为value放入哈希表中 第二步我们再遍历原链表这次我们要将新链表的next和random指针给设置上 从上图中我们可以发现原节点和新节点是一一对应的关系所以
map.get(原节点)得到的就是对应的新节点map.get(原节点.next)得到的就是对应的新节点.nextmap.get(原节点.random)得到的就是对应的新节点.random
所以我们只需要再次遍历原链表然后设置 新节点.next - map.get(原节点.next) 新节点.random - map.get(原节点.random) 这样新链表的next和random都被串联起来了 最后我们然后map.get(head)也就是对应的新链表的头节点就可以解决此问题了。
代码
class Solution {public Node copyRandomList(Node head) {if(headnull) {return null;}//创建一个哈希表key是原节点value是新节点MapNode,Node map new HashMapNode,Node();Node p head;//将原节点和新节点放入哈希表中while(p!null) {Node newNode new Node(p.val);map.put(p,newNode);p p.next;}p head;//遍历原链表设置新节点的next和randomwhile(p!null) {Node newNode map.get(p);//p是原节点map.get(p)是对应的新节点p.next是原节点的下一个//map.get(p.next)是原节点下一个对应的新节点if(p.next!null) {newNode.next map.get(p.next);}//p.random是原节点随机指向//map.get(p.random)是原节点随机指向 对应的新节点 if(p.random!null) {newNode.random map.get(p.random);}p p.next;}//返回头结点即原节点对应的value(新节点)return map.get(head);}
}
总结
最好的方法我觉得还是方法3这个方法不仅思路简单代码也简单。方法2虽然思路简单但是写代码不好写所以要多去想哈希表原来哈希表的key 和 value 可以分别存放两个链表所以以后看到复杂链表的复制要去想用哈希表来复制。