进击的骑士
难度:
标签:
题目描述
代码结果
运行时间: 35 ms, 内存: 0.0 MB
// 题目思路: 这是一个广度优先搜索(BFS)问题。我们使用Java Stream API来简化代码结构和提高可读性。
// 骑士有8种走法,我们需要找到从(0, 0)到(x, y)的最短路径。
// 使用队列存储骑士的位置和步数,并使用集合记录访问过的位置。
import java.util.*;
import java.util.stream.*;
public class Solution {
public int minKnightMoves(int x, int y) {
x = Math.abs(x);
y = Math.abs(y);
int[][] directions = {{1, 2}, {2, 1}, {2, -1}, {1, -2},
{-1, -2}, {-2, -1}, {-2, 1}, {-1, 2}};
Queue<int[]> queue = new LinkedList<>();
Set<String> visited = new HashSet<>();
queue.add(new int[] {0, 0});
visited.add("0,0");
int steps = 0;
while (!queue.isEmpty()) {
final int size = queue.size();
steps += IntStream.range(0, size).map(i -> {
int[] current = queue.poll();
int currX = current[0], currY = current[1];
if (currX == x && currY == y) {
queue.clear(); // 结束循环
return -1; // 表示找到结果
}
Arrays.stream(directions).forEach(direction -> {
int newX = currX + direction[0];
int newY = currY + direction[1];
String pos = newX + "," + newY;
if (!visited.contains(pos) && newX >= -1 && newY >= -1) {
queue.add(new int[] {newX, newY});
visited.add(pos);
}
});
return 0; // 表示未找到结果
}).sum();
if (steps < 0) return steps + 1; // 修正步数
}
return -1; // 不会到达这里
}
}
解释
方法:
该题解使用了贪心算法和广度优先搜索(BFS)的组合来找到从原点(0,0)到目标位置(x,y)的最少骑士移动次数。首先,由于骑士的移动是对称的,我们只考虑x和y的绝对值。在较大的坐标区域(x或y大于4),使用贪心算法快速减少距离,每次尽可能地向目标位置靠近。当x和y都小于等于4时,转而使用BFS考虑所有可能的骑士移动,直到找到到达目标坐标(x, y)的最短路径。该方法先快速减少距离,后细致搜索,平衡了效率和准确性。
时间复杂度:
O(max(x, y))
空间复杂度:
O(1)
代码细节讲解
🦆
为什么在x或y大于4时使用贪心算法而不是从一开始就使用BFS?
▷🦆
在贪心算法中,选择`x -= 2`和`y -= 1`的依据是什么?如何确定这样的移动是最优的?
▷🦆
在BFS搜索中,判断`(x - i) * di > 0 or (y - j) * dj > 0`的条件是为了什么?这是否确保了每一步都在接近目标?
▷🦆
BFS部分如何处理重复状态或是已访问过的坐标点?题解中未提及使用任何避免重复的机制,这会如何影响性能?
▷