游乐园的迷宫
难度:
标签:
题目描述
English description is not available for the problem. Please switch to Chinese.
代码结果
运行时间: 874 ms, 内存: 16.6 MB
/*
题目思路:
1. 使用 Java Stream API 遍历 points 确定每次转向方向。
2. 使用 direction 字符串的每个字符确定下一个点。
3. 输出一个满足条件的路径。
*/
import java.util.*;
import java.util.stream.IntStream;
public class SalesmanPathStream {
public List<Integer> findPath(int[][] points, String direction) {
List<Integer> path = new ArrayList<>();
path.add(0); // 从第一个点开始
Set<Integer> visited = new HashSet<>();
visited.add(0);
int prev = 0;
direction.chars().forEach(d -> {
OptionalInt nextPoint = IntStream.range(1, points.length)
.filter(i -> !visited.contains(i))
.filter(i -> isValidTurn(points, prev, path.get(path.size() - 1), i, (char) d))
.findFirst();
nextPoint.ifPresent(i -> {
path.add(i);
visited.add(i);
prev = path.get(path.size() - 2);
});
});
path.add(path.get(0)); // 回到起点
return path;
}
private boolean isValidTurn(int[][] points, int prev, int current, int next, char direction) {
int[] v1 = {points[current][0] - points[prev][0], points[current][1] - points[prev][1]};
int[] v2 = {points[next][0] - points[current][0], points[next][1] - points[current][1]};
int crossProduct = v1[0] * v2[1] - v1[1] * v2[0];
return (direction == 'L' && crossProduct > 0) || (direction == 'R' && crossProduct < 0);
}
public static void main(String[] args) {
SalesmanPathStream sp = new SalesmanPathStream();
int[][] points = {{1, 3}, {2, 4}, {3, 3}, {2, 1}};
String direction = "LR";
System.out.println(sp.findPath(points, direction));
}
}
解释
方法:
本题解采用的方法是基于模拟顺序搜索的策略,主要步骤包括:1) 找到最左侧的点作为起始点;2) 根据给定的转向指令序列依次选择下一个访问点。在选择过程中,如果当前转向指令是'L',则从未访问的点中选择相对于当前向量方向最右侧的点;如果指令是'R',则选择相对方向最左侧的点。这通过计算向量的叉积来判定。最后,将未访问的点添加到路径中作为终点。这种方法确保了每个点被恰好访问一次,并且满足转向的要求。
时间复杂度:
O(N^2)
空间复杂度:
O(N)
代码细节讲解
🦆
在确定最左侧的点作为起始点的基础上,如何保证任意起点和终点的选择也能满足题目要求?
▷🦆
在寻找转向'L'时最右侧点和转向'R'时最左侧点的过程中,叉积的符号是如何准确反映点的相对位置的?
▷🦆
叉积计算中,为什么向量的起点始终是上一个选择的点,这种设置对算法的结果有何影响?
▷