找出数组中的所有 K 近邻下标
遍历 nums 找到所有 key 的下标,然后将其左右 k 范围内的下标加到答案数组中即可。
class Solution {
public List<Integer> findKDistantIndices(int[] nums, int key, int k) {
List<Integer> res = new ArrayList<>();
int last = -1;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == key) {
for (int j = Math.max(last + 1, i - k); j <= i + k && j < nums.length; j++) {
res.add(j);
last = j;
}
}
}
return res;
}
}
统计可以提取的工件
二维前缀和的典型应用场景。
class Solution {
public int digArtifacts(int n, int[][] artifacts, int[][] dig) {
int[][] map = new int[n][n];
for (var p : dig) {
map[p[0]][p[1]] = 1;
}
// preSum[i][j] = (0, 0) ~ (i-1, j-1) square
int[][] preSum = new int[n + 1][n + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
preSum[i][j] = map[i - 1][j - 1] + preSum[i - 1][j] + preSum[i][j - 1] - preSum[i - 1][j - 1];
}
}
int res = 0;
for (var p : artifacts) {
int sum = preSum[p[2] + 1][p[3] + 1] - preSum[p[2] + 1][p[1]] - preSum[p[0]][p[3] + 1] + preSum[p[0]][p[1]];
int real = (p[3] - p[1] + 1) * (p[2] - p[0] + 1);
if (sum == real) {
res++;
}
}
return res;
}
}
K 次操作后最大化顶端元素
枚举每个位置,判断这个位置经过 k 次操作后能否变成栈顶。详见注释。
class Solution {
public int maximumTop(int[] nums, int k) {
int res = -1;
for (int i = 0; i < nums.length; i++) {
if (verify(i, k, nums.length)) {
res = Math.max(res, nums[i]);
}
}
return res;
}
// 判断 k 次操作后能否使得 idx 位置的元素变成栈顶
private boolean verify(int idx, int k, int length) {
if (k <= idx) {
return k == idx; // k < idx 时说明一直弹出也无法使得 idx 达到栈顶;k == idx 时恰好达到栈顶。
}
if (length == 1) {
return k % 2 == 0; // 只有一个元素,此时只能弹出、放回、弹出、放回
}
return k != idx + 1; // 有多个元素,且 k > idx,此时只有在 k == idx + 1 的时候无法做到,因为这时相当于 k == 1 && idx == 0
}
}
得到要求路径的最小带权子图
求出 src1 到其他所有节点的最短路,然后枚举 src2 到 dest 的所有路径,每找到一条路径 X,枚举 src1 到这个路径上每一个点的最短路 Y, 此时 X 和 Y 的长度和就可以作为备选答案。
class Solution {
long res;
public long minimumWeight(int n, int[][] edges, int src1, int src2, int dest) {
Dijkstra dijkstra = new Dijkstra(n);
for (int[] edge : edges) {
dijkstra.addEdge(edge[0], edge[1], edge[2]);
}
long[] src1MinPath = dijkstra.dijkstra(src1);
res = Long.MAX_VALUE;
boolean[] vis = new boolean[n];
int[] path = new int[n];
vis[src2] = true;
path[0] = src2;
dfs(src2, dest, dijkstra.graph, src1MinPath, vis, path, 1, 0);
return res == Long.MAX_VALUE ? -1 : res;
}
private void dfs(int cur, int dest, List<List<Dijkstra.Node>> graph, long[] src1MinPath, boolean[] vis, int[] path, int pathLen, long len) {
if (cur == dest) {
for (int i = 0; i < pathLen; i++) {
if (src1MinPath[path[i]] < Long.MAX_VALUE) {
res = Math.min(res, len + src1MinPath[path[i]]);
}
}
return;
}
for (var nxt : graph.get(cur)) {
if (vis[nxt.to]) {
continue;
}
vis[nxt.to] = true;
path[pathLen] = nxt.to;
dfs(nxt.to, dest, graph, src1MinPath, vis, path, pathLen + 1, len + nxt.len);
vis[nxt.to] = false;
}
}
}
class Dijkstra {
static class Node {
int to;
long len;
Node(int to, long len) {
this.to = to;
this.len = len;
}
}
List<List<Node>> graph;
public Dijkstra(int size) {
graph = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
graph.add(new ArrayList<>());
}
}
public void addEdge(int from, int to, long len) {
graph.get(from).add(new Node(to, len));
}
public long[] dijkstra(int start) {
long[] res = new long[graph.size()];
Arrays.fill(res, Long.MAX_VALUE);
res[start] = 0;
PriorityQueue<Node> heap = new PriorityQueue<>((o1, o2) -> (int) (o1.len - o2.len));
heap.add(new Node(start, 0));
boolean[] visited = new boolean[graph.size()];
while (!heap.isEmpty()) {
Node node = heap.poll();
if (visited[node.to]) {
continue;
}
visited[node.to] = true;
for (Node next : graph.get(node.to)) {
if (res[next.to] > node.len + next.len) {
res[next.to] = node.len + next.len;
heap.add(new Node(next.to, node.len + next.len));
}
}
}
return res;
}
}
\