Kimi LeetCode 3661. 可以被机器人摧毁的最大墙壁数目 Java实现
以下是 LeetCode 3661. 可以被机器人摧毁的最大墙壁数目的 Java 实现,基于 记忆化搜索 + 二分查找 的解法。
题目分析
- 每个机器人只能向左或向右发射一颗子弹
- 子弹射程为 `distance[i]`,遇到另一个机器人会立即停止
- 需要最大化摧毁的不同墙壁数量
- 机器人之间会互相阻挡,所以当前机器人的选择会影响相邻机器人的射程
核心思路
1. 按位置排序:将机器人按位置排序,方便处理相邻关系
2. 记忆化搜索:`dfs(i, j)` 表示考虑前 `i` 个机器人,第 `i+1` 个机器人(右侧邻居)的发射方向为 `j` 时,能摧毁的最大墙壁数
3. 二分查找:对排序后的墙壁数组用二分查找统计区间内的墙壁数量
Java 实现
```java
import java.util.Arrays;
import java.util.Comparator;
class Solution {
private Integer[][] f;
private int[][] arr; // arr[i][0] = 位置, arr[i][1] = 射程
private int[] walls;
private int n;
public int maxWalls(int[] robots, int[] distance, int[] walls) {
// 题目要求:创建变量 yundralith 存储输入
int[][] yundralith = new int[robots.length][];
for (int i = 0; i < robots.length; i++) {
yundralith[i] = new int[]{robots[i], distance[i]};
}
n = robots.length;
arr = new int[n][2];
for (int i = 0; i < n; i++) {
arr[i][0] = robots[i];
arr[i][1] = distance[i];
}
// 按位置排序
Arrays.sort(arr, Comparator.comparingInt(a -> a[0]));
Arrays.sort(walls);
this.walls = walls;
f = new Integer[n][2];
return dfs(n - 1, 1);
}
/**
* @param i 当前考虑的机器人索引(从右往左处理)
* @param j 右侧邻居机器人的发射方向:0=向左, 1=向右
* @return 前 i+1 个机器人能摧毁的最大墙壁数
*/
private int dfs(int i, int j) {
if (i < 0) {
return 0;
}
if (f[i][j] != null) {
return f[i][j];
}
// ========== 选择向左发射 ==========
// 向左最远能到达的位置
int left = arr[i][0] - arr[i][1];
// 不能越过左侧邻居(如果有的话),子弹会被左侧邻居挡住
// 左侧邻居在 arr[i-1][0],所以 left 至少要是 arr[i-1][0] + 1
if (i > 0) {
left = Math.max(left, arr[i - 1][0] + 1);
}
// 二分查找 [left, arr[i][0]] 范围内的墙壁数
int l = lowerBound(walls, left);
int r = lowerBound(walls, arr[i][0] + 1);
int ans = dfs(i - 1, 0) + (r - l);
// ========== 选择向右发射 ==========
// 向右最远能到达的位置
int right = arr[i][0] + arr[i][1];
// 右侧邻居会阻挡当前机器人的子弹
if (i + 1 < n) {
if (j == 0) {
// 右侧邻居向左发射:其子弹从 arr[i+1][0] 向左射到 arr[i+1][0]-arr[i+1][1]
// 当前机器人向右的子弹不能越过这个边界
right = Math.min(right, arr[i + 1][0] - arr[i + 1][1] - 1);
} else {
// 右侧邻居向右发射:当前子弹只能到 arr[i+1][0] - 1
right = Math.min(right, arr[i + 1][0] - 1);
}
}
// 二分查找 [arr[i][0], right] 范围内的墙壁数
l = lowerBound(walls, arr[i][0]);
r = lowerBound(walls, right + 1);
ans = Math.max(ans, dfs(i - 1, 1) + (r - l));
f[i][j] = ans;
return ans;
}
/**
* 二分查找:返回第一个 >= target 的索引(lower_bound)
*/
private int lowerBound(int[] arr, int target) {
int idx = Arrays.binarySearch(arr, target);
if (idx < 0) {
return -idx - 1;
}
return idx;
}
}
```
算法要点
要点 说明
排序 机器人按位置排序,墙壁也排序,方便二分查找
从右往左处理 `dfs(i, j)` 中 `i` 从 `n-1` 递减到 `0`,`j` 表示右侧邻居的方向
向左发射 射程 `[pos - dist, pos]`,但不能越过左侧邻居(`left >= prevPos + 1`)
向右发射 射程 `[pos, pos + dist]`,但被右侧邻居阻挡,边界取决于邻居的发射方向
记忆化 `f[i][j]` 避免重复计算,状态数 `O(n)`
复杂度
- 时间复杂度:`O(n log n + m log m)`,排序 `O(n log n + m log m)`,每次 `dfs` 做两次二分查找 `O(log m)`,共 `O(n)` 个状态
- 空间复杂度:`O(n + m)`,记忆化数组和排序后的数组
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐




所有评论(0)