[Leetcode Weekly Contest]284
链接:LeetCode
[Leetcode]2200. 找出数组中的所有 K 近邻下标
给你一个下标从 0 开始的整数数组 nums 和两个整数 key 和 k 。K 近邻下标 是 nums 中的一个下标 i ,并满足至少存在一个下标 j 使得 |i - j| <= k 且 nums[j] == key 。
以列表形式返回按 递增顺序 排序的所有 K 近邻下标。
遍历即可。
class Solution {
public List<Integer> findKDistantIndices(int[] nums, int key, int k) {
LinkedList<Integer> res = new LinkedList<>();
List<Integer> indexs = new ArrayList<>();
for(int i=0;i<nums.length;++i) {
if(nums[i] == key) indexs.add(i);
}
for(var index:indexs) {
for(int value=index-k;value<=index+k; value++) {
if(value < 0 || value >= nums.length) continue;
if(!res.isEmpty() && value<=res.getLast()) continue;
else res.add(value);
}
}
return res;
}
}
[Leetcode]2201. 统计可以提取的工件
存在一个 n x n 大小、下标从 0 开始的网格,网格中埋着一些工件。给你一个整数 n 和一个下标从 0 开始的二维整数数组 artifacts ,artifacts 描述了矩形工件的位置,其中 artifacts[i] = [r1i, c1i, r2i, c2i] 表示第 i 个工件在子网格中的填埋情况:
(r1i, c1i) 是第 i 个工件 左上 单元格的坐标,且
(r2i, c2i) 是第 i 个工件 右下 单元格的坐标。
你将会挖掘网格中的一些单元格,并清除其中的填埋物。如果单元格中埋着工件的一部分,那么该工件这一部分将会裸露出来。如果一个工件的所有部分都都裸露出来,你就可以提取该工件。
给你一个下标从 0 开始的二维整数数组 dig ,其中 dig[i] = [ri, ci] 表示你将会挖掘单元格 (ri, ci) ,返回你可以提取的工件数目。
生成的测试用例满足:
不存在重叠的两个工件。
每个工件最多只覆盖 4 个单元格。
dig 中的元素互不相同。
哈希表,记录每个工件所在位置。
class Solution {
public int digArtifacts(int n, int[][] artifacts, int[][] dig) {
HashMap<Integer, List<String>> artifactsMap = new HashMap<>();
HashSet<String> digSet = new HashSet<>();
for(int i=0;i<artifacts.length;++i) {
int r1 = artifacts[i][0], c1 = artifacts[i][1], r2 = artifacts[i][2], c2 = artifacts[i][3];
List<String> indexs = new ArrayList<>();
for(int r=r1;r<=r2;r++) {
for(int c=c1;c<=c2;c++) {
indexs.add(""+r+"-"+c);
}
}
artifactsMap.put(i, indexs);
}
for(var d:dig) digSet.add(""+d[0]+"-"+d[1]);
int res = 0;
for(var artifactsValue:artifactsMap.values()) {
boolean succeed = true;
for(var val: artifactsValue) {
if (!digSet.contains(val)) {
succeed=false;
break;
}
}
if(succeed) res ++;
}
return res;
}
}
[Leetcode]2202. K 次操作后最大化顶端元素
给你一个下标从 0 开始的整数数组 nums ,它表示一个 栈 ,其中 nums[0] 是栈顶的元素。
每一次操作中,你可以执行以下操作 之一 :
如果栈非空,那么 删除 栈顶端的元素。
如果存在 1 个或者多个被删除的元素,你可以从它们中选择任何一个,添加 回栈顶,这个元素成为新的栈顶元素。
同时给你一个整数 k ,它表示你总共需要执行操作的次数。
请你返回 恰好 执行 k 次操作以后,栈顶元素的 最大值 。如果执行完 k 次操作以后,栈一定为空,请你返回 -1 。
枚举,分情况讨论即可。注意要特别判断下执行完 k 次操作以后,栈一定为空的情况。
class Solution {
public int maximumTop(int[] nums, int k) {
int n = nums.length;
if(n == 1) return (k&1)!=0 ? -1:nums[0];
if(k == 0) return nums[0];
if(k == 1) return nums[1];
if(k>=n+1) return Arrays.stream(nums).max().getAsInt();
if(k == n) return Arrays.stream(Arrays.copyOfRange(nums, 0, n-1)).max().getAsInt();
else {
return Math.max(nums[k], Arrays.stream(Arrays.copyOfRange(nums, 0, k-1)).max().getAsInt());
}
}
}
[Leetcode]2203. 得到要求路径的最小带权子图
给你一个整数 n ,它表示一个 带权有向 图的节点数,节点编号为 0 到 n - 1 。
同时给你一个二维整数数组 edges ,其中 edges[i] = [fromi, toi, weighti] ,表示从 fromi 到 toi 有一条边权为 weighti 的 有向 边。
最后,给你三个 互不相同 的整数 src1 ,src2 和 dest ,表示图中三个不同的点。
请你从图中选出一个 边权和最小 的子图,使得从 src1 和 src2 出发,在这个子图中,都 可以 到达 dest 。如果这样的子图不存在,请返回 -1 。
子图 中的点和边都应该属于原图的一部分。子图的边权和定义为它所包含的所有边的权值之和。
求三次最短路,dijkstra算法。
我们可以枚举三岔口的交点 x,然后求 \(\textit{src1}\) 和 \(\textit{src2}\) 到 x 的最短路,以及 x 到 \(\textit{dest}\) 的最短路,这可以通过在反图(即所有边反向后的图)上求从 \(\textit{dest}\) 出发的最短路得出。
累加这三条最短路的和,即为三岔口在 x 处的子图的边权和。
class Solution {
public long minimumWeight(int n, int[][] edges, int src1, int src2, int dest) {
List<int[]>[] graph = new ArrayList[n];
List<int[]>[] reversedGraph = new ArrayList[n];
for(int i=0;i<n;++i) {
graph[i]=new ArrayList<>();
reversedGraph[i]=new ArrayList<>();
}
for(var edge: edges) {
int from = edge[0], to = edge[1], weight = edge[2];
graph[from].add(new int[] {to, weight});
reversedGraph[to].add(new int[] {from, weight});
}
long[] dis1 = dijkstra(graph, src1);
long[] dis2 = dijkstra(graph, src2);
long[] dis3 = dijkstra(reversedGraph, dest);
long res = Long.MAX_VALUE/3;
for(int i=0;i<n;++i) {
res = Math.min(res, dis1[i]+dis2[i]+dis3[i]);
}
return res<Long.MAX_VALUE/3?res:-1;
}
public long[] dijkstra(List<int[]>[] graph, int source) {
long[] res = new long[graph.length];
Arrays.fill(res, Long.MAX_VALUE/3);
res[source] = 0;
Queue<long[]> deque = new PriorityQueue<>((a, b) -> Long.compare(a[1], b[1]));
deque.add(new long[]{source, 0L});
while(!deque.isEmpty()) {
var pop = deque.poll();
int ind = (int)pop[0];
long dis = pop[1];
if(dis > res[ind]) continue;
for(var nxt:graph[ind]) {
int nxtInd = nxt[0], nxtDis = nxt[1];
if(nxtDis+dis < res[nxtInd]) {
res[nxtInd] = nxtDis+dis;
deque.add(new long[]{nxtInd, nxtDis+dis});
}
}
}
return res;
}
}