第二天
又是被字节校园每日一题香到的一天呢!
我的刷题笔记
复制带随机指针的链表
给你一个长度为n的链表 每个节点包含一个额外增加的随机指针random
这个指针可以指向链表中的任何节点或空节点
构造这个链表的深拷贝
深拷贝应该正好由n个全新节点组成 其中每个新节点的值都设为其对应的原节点的值。
新节点的next random指针也都应该指向复制链表中的新节点 并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
例如 如果原链表中有X Y两个节点 其中
X.random-->Y
那么在复制链表中对应的两个节点x 和 y 同样有x.random--y>
返回复制链表的头节点
用一个由n个节点组成的链表来表示输入/输出中的链表 每个节点用一个[val, random_index]
表示
val
一个表示 Node.val的整数random_index
随机指针指向的节点索引(范围从0到n-1)如果不指向任何节点 则为null我们的代码只接受原链表的头节点head
作为传入参数
我们的有向链表长这样——
”复制随机指针“是本题的最大难点
本题参考题解两种实现+图解 138. 复制带随机指针的链表
来看一看哈希表的做法~
【1】创建一个哈希表 再遍历原链表 遍历的同时再不断创建新节点!
【2】我们将原节点作为key——键 新节点作为value——值 放入哈希表中
【3】我们开始遍历原链表
如图 我们将新链表的next 和 random指针给设置上!(就是黑咕隆咚那个箭头~)
【4】如上图 原节点、新节点是一一对应的关系,所以 ——
Map是Java.util中的集合类中最常用的集合类之一(另一个是List)
Map 提供了一个更通用的元素存储方法。Map 集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值。
【5】再次遍历原链表!然后设置
新节点.next->map.get(原节点.next)
新节点.random->map.get(原节点.random)
这样新链表的next 和 random就都被串联起来了~
【6】最后返回头节点得到结果 map.get(head)
好多时候我在想 跟着大佬们的思路把代码过一遍还没点儿自己的感悟有资格写这个“代码逻辑”么?
没有吧
之后的代码逻辑part要有感而发!
上面的题解已经很清楚了~
之后了解更多这道题再来看~
class Solution { public Node copyRandomList(Node head) { if(head == null) { return null; } //创建一个哈希表map key是原节点 value是新节点 Map<Node, Node> map = new HashMap<Node, Node>(); //利用java.util中的集合类Map Node p = head; //将原节点和新节点放入哈希表中 while(p != null) { Node newNode = new Node(p.val); map.put(p,newNode);//将原节点p和新节点newNode全添加到哈希表中~ p = p.next;//p从头节点开始 一直到 遍历完集合中的最后一个元素 } p = head; //遍历原链表 设置新节点的next 和 random while(p != null) { Node newNode = map.get(p); //p是原节点 map.get(p)是对应的新节点 //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; } //返回头节点 return map.get(head); } }
我的刷题笔记
两个数组的交集II
参考题解 【双指针】两个数组的交集 II
我们要寻找两数组是否有相同项 并且提示中说可以不要求交集的顺序——
【0】所以我们可以先将数组排序 方便我们进行查找~
【1】创建指针i指向nums1
数组首位 指针j指向nums2
数组首位(C++使用指针 Java直接用数组解决问题)
【2】创建用来存放结果集的临时栈intersection
【3】开始比较指针i j的大小 如果两个值不等 则数字小的指针往右一位
【4】若指针i和指针j的值相等 则将交集压入栈
【5】若nums或nums2有一方遍历结束 代表另一方的剩余值 都是唯一存在 且不会与之产生交集的 所以循环的条件为index1 <length && index2 < length2
—— 只要有一方不符合(遍历结束) 就直接遍历结束~
【1】使用Arrays类中的排序方法来排序两个数组
【2】创建存放结果的临时栈——intersection
【3】之后进行快乐的数组遍历 不要忘了先定义好索引哦~
【4】遍历的过程中 如果两个数组nums1/nums2
谁的元素更小一些 则让它的索引index1/index2
++(排好序了就是轻松鸭!)
【4‘】遍历的过程中 如果两个数组nums1
和nums2
有相同的元素 则添加到临时栈中(不要忘了把临时栈中的索引index
++~
class Solution { public int[] intersect(int [] nums1, int[] nums2){ Arrays.sort(nums1);//排序nums1数组 Arrays.sort(nums2);//排序nums2数组 int length1 = nums1.length, length2 = nums2.length; int [] intersection = new int [Math.min(length1, length2)];//创建存放结果的临时栈 intersection //选数组长度最短的那个length作为存放结果集的临时栈 int index1 = 0, index2 = 0, index = 0;//定义好这些索引 一会儿遍历数组的时候要用到 while (index1 < length1 && index2 < length2){ if (nums1[index1] < nums2[index2])//因为排好序了 所以就可以为所欲为了hhh //谁小谁索引加一下~ index1 ++; else if(nums1[index1] > nums2[index2]){ index2 ++; } else { intersection[index] = nums1[index1];//存放结果的临时栈中加入相同的那一位 index1 ++; index2 ++; index ++; } } return Arrays.copyOfRange(intersection, 0, index); } }
最后对copyOfRange(intersection, 0, index)
函数做个简单介绍——
来自java.long类(用于操作数组的一个类)
copyOfRange(intersection, 0, index)
函数是返回一个长度为index-0
的数组intersection