leetcode
leetcode 3001 ~ 3050
自行车炫技赛场

自行车炫技赛场

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 43 ms, 内存: 16.8 MB


/*
思路:
1. 通过流式处理和广度优先搜索结合来解决问题。
2. 使用Queue来处理每个位置的速度变化,并使用流来筛选和排序结果。
*/
import java.util.*;
import java.util.stream.Collectors;
public class BikeRaceStream {
    public List<int[]> findPositions(int[] position, int[][] terrain, int[][] obstacle) {
        int n = terrain.length;
        int m = terrain[0].length;
        List<int[]> result = new ArrayList<>();
        boolean[][] visited = new boolean[n][m];
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[]{position[0], position[1], 1}); // {row, col, speed}
        int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        while (!queue.isEmpty()) {
            int[] current = queue.poll();
            int row = current[0];
            int col = current[1];
            int speed = current[2];
            Arrays.stream(directions).forEach(dir -> {
                int newRow = row + dir[0];
                int newCol = col + dir[1];
                if (newRow >= 0 && newRow < n && newCol >= 0 && newCol < m && !visited[newRow][newCol]) {
                    int newSpeed = speed + terrain[row][col] - terrain[newRow][newCol] - obstacle[newRow][newCol];
                    if (newSpeed == 1) {
                        result.add(new int[]{newRow, newCol});
                        visited[newRow][newCol] = true;
                        queue.offer(new int[]{newRow, newCol, newSpeed});
                    }
                }
            });
        }
        return result.stream().sorted((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]).collect(Collectors.toList());
    }
    public static void main(String[] args) {
        BikeRaceStream bikeRace = new BikeRaceStream();
        int[] position = {1, 1};
        int[][] terrain = {{5, 0}, {0, 6}};
        int[][] obstacle = {{0, 6}, {7, 0}};
        List<int[]> result = bikeRace.findPositions(position, terrain, obstacle);
        result.forEach(pos -> System.out.println(Arrays.toString(pos)));
    }
}

解释

方法:

题解采用了宽度优先搜索(BFS)的策略来寻找所有可能的速度为1的位置。初始位置及速度被加入队列,并通过一个集合来防止重复访问相同的状态(位置和速度)。从队列中取出当前位置,遍历四个可能的移动方向(上、下、左、右)。对于每一个合法的新位置,计算新的速度,若速度大于0且该状态未被访问过,则加入队列继续搜索。如果新的速度恰好为1,该位置则加入结果列表。最后,结果按要求排序后返回。

时间复杂度:

O(N*M*V)

空间复杂度:

O(N*M*V)

代码细节讲解

🦆
怎样确保在宽度优先搜索中正确处理速度变化为负值的情况,即当速度变化值`speed_new`为负时,如何处理该状态?
在本题中,速度变化为负值意味着自行车无法继续前进,因为速度不能小于或等于零。因此,当计算出的新速度`speed_new`为负或零时,这个新状态不会被加入队列进行进一步的搜索。这是因为速度为负或零意味着自行车停止运动,不再具有继续探索其他位置的能力。只有当`speed_new`大于零时,该状态才可能继续前进,并且有可能达到其他的速度为1的位置。
🦆
在题解中,为什么选用宽度优先搜索(BFS)而不是深度优先搜索(DFS)作为遍历算法?
在这个问题中,使用宽度优先搜索(BFS)是为了确保在探索所有可能的位置和速度组合时,可以更均匀和系统地遍历各个可能的状态。BFS通过逐层探索所有可能的移动,帮助确保找到所有速度恰好为1的位置。相比之下,深度优先搜索(DFS)可能会导致算法过早地深入一个方向,从而可能错过更近的、速度为1的位置。此外,BFS在处理状态空间搜索问题时通常更容易管理和预测性能,特别是当状态空间较大时。
🦆
题解中对于新位置的合法速度检查是`speed_new > 0`,能否详细解释速度为零的情况为何不考虑加入队列?
在这个题解当中,速度为零的情况不被考虑加入队列,是因为速度为零意味着自行车已经停止,不能继续前进到任何新的位置。这与题目的要求相违背,因为目标是探索从初始位置开始,速度恰好再次变为1时的可达位置。如果速度为零,则无法继续探索,也就无法达到速度再次为1的状态。因此,只有当速度大于零时,才能继续探索并可能找到符合条件的位置。

相关问题