leetcode
leetcode 1001 ~ 1050
进击的骑士

进击的骑士

难度:

标签:

题目描述

代码结果

运行时间: 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或y大于4时使用贪心算法可以快速减少到目标的距离,从而减少计算量和提高效率。贪心算法在大尺度上能够有效地接近目标,因此适合在较大的坐标区域使用。相较之下,BFS虽然可以找到最优解,但在大规模搜索时非常耗时和内存消耗大,因为需要探索大量的状态。因此,结合使用贪心算法和BFS,可以在保证找到最短路径的同时,尽可能提高算法的效率。
🦆
在贪心算法中,选择`x -= 2`和`y -= 1`的依据是什么?如何确定这样的移动是最优的?
选择`x -= 2`和`y -= 1`是基于骑士在棋盘上的移动方式(L形)。此种移动方式能够在保持x和y都减小的同时,使用最少的步数接近目标位置。虽然这样的移动在局部看来不一定是最优的,但在全局上,这种策略能够快速减少x和y的值,尤其是当x和y相差较大时。在实际应用中,此策略经常能有效减少计算步骤,尽管它不保证每一步都是局部最优解。
🦆
在BFS搜索中,判断`(x - i) * di > 0 or (y - j) * dj > 0`的条件是为了什么?这是否确保了每一步都在接近目标?
在BFS搜索中,条件`(x - i) * di > 0 or (y - j) * dj > 0`用于确定移动的方向是否使得当前位置接近目标位置。此条件确保了在x或y方向上的移动是朝向目标的,避免了向远离目标的方向移动。这种方式可以减少无效的探索和提高搜索的效率,确保每一步都在尽可能地接近目标。
🦆
BFS部分如何处理重复状态或是已访问过的坐标点?题解中未提及使用任何避免重复的机制,这会如何影响性能?
题解中未提及处理重复状态或已访问过的坐标点的机制,这可能会导致算法效率降低,因为可能会重复探索同一坐标点。在实际应用中,通常会使用一个集合或数组来记录已访问过的位置,防止重复访问,从而提高效率。未使用此机制可能会导致BFS搜索的时间和空间复杂度增加。

相关问题