Java 找到有障碍物的两点之间的最短路径
我需要在给定障碍物的网格中找到两点之间的最短路径 给定一个二维矩阵,其中一些元素被填充 用1填充,其余元素将被填充。这里X表示你不能 遍历到那个特定的点。从一个细胞你可以 向左、向右、向上或向下移动。给定矩阵中的两点 找到这些点之间的最短路径。这是开始 点,E是终点 我提出了下面的代码,但我想从访谈的角度了解解决这个问题最有效的算法是什么?有没有更好的办法Java 找到有障碍物的两点之间的最短路径,java,algorithm,data-structures,breadth-first-search,Java,Algorithm,Data Structures,Breadth First Search,我需要在给定障碍物的网格中找到两点之间的最短路径 给定一个二维矩阵,其中一些元素被填充 用1填充,其余元素将被填充。这里X表示你不能 遍历到那个特定的点。从一个细胞你可以 向左、向右、向上或向下移动。给定矩阵中的两点 找到这些点之间的最短路径。这是开始 点,E是终点 我提出了下面的代码,但我想从访谈的角度了解解决这个问题最有效的算法是什么?有没有更好的办法 public static void main(String[] args) { char[][] matrix = {{'1
public static void main(String[] args) {
char[][] matrix = {{'1','1','1', '1'},
{'1','S','1', '1'},
{'1','1','X', '1'},
{'1','1','1', 'E'}};
System.out.println(shortestPath(matrix));
}
public static int shortestPath(char[][] matrix) {
int s_row = 0, s_col = 0;
boolean flag = false;
for (s_row = 0; s_row < matrix.length; s_row++) {
for (s_col = 0; s_col < matrix[0].length; s_col++) {
if (matrix[s_row][s_col] == 'S')
flag = true;
if (flag)
break;
}
if (flag)
break;
}
return shortestPath(matrix, s_row, s_col);
}
public static int shortestPath(char[][] matrix, int s_row, int s_col) {
int count = 0;
Queue<int[]> nextToVisit = new LinkedList<>();
nextToVisit.offer(new int[] {s_row, s_col});
Set<int[]> visited = new HashSet<>();
Queue<int[]> temp = new LinkedList<>();
while (!nextToVisit.isEmpty()) {
int[] position = nextToVisit.poll();
int row = position[0];
int col = position[1];
if (matrix[row][col] == 'E')
return count;
if (row > 0 && !visited.contains(new int[] {row - 1, col}) && matrix[row - 1][col] != 'X')
temp.offer(new int[] {row - 1, col});
if (row < matrix.length - 1 && !visited.contains(new int[] {row + 1, col})
&& matrix[row + 1][col] != 'X')
temp.offer(new int[] {row + 1, col});
if (col > 0 && !visited.contains(new int[] {row, col - 1}) && matrix[row][col - 1] != 'X')
temp.offer(new int[] {row, col - 1});
if (col < matrix[0].length - 1 && !visited.contains(new int[] {row, col + 1})
&& matrix[row][col + 1] != 'X')
temp.offer(new int[] {row, col + 1});
if (nextToVisit.isEmpty() && !temp.isEmpty()) {
nextToVisit = temp;
temp = new LinkedList<>();
count++;
}
}
return count;
}
对于这类问题,最有效的算法是如果从一个点到另一个点的成本是固定的。如果成本是可变的,但为正,那么您需要使用,如果存在负成本的可能性,则将是正确的选择
还有一件事,为了让自己适应这类问题,一种方法是更多地解决这类问题。您将在站点中找到此类问题。解决此类问题的最有效算法是,如果从一个点到另一个点的成本是固定的。如果成本是可变的,但为正,那么您需要使用,如果存在负成本的可能性,则将是正确的选择 还有一件事,为了让自己适应这类问题,一种方法是更多地解决这类问题。您将在站点中发现此类问题。希望这有帮助-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import GridNavigationTest.Direction;
public class GridNavigationTest {
public static final int[][] navigableGrid = new int[][] {
{ 1, 1, 1, 1 },
{ 1, 0, 0, 1 },
{ 1, 0, 1, 1 },
{ 1, 0, 1, 0 },
{ 1, 1, 9, 0 }
};
public enum Direction {
UP, DOWN, RIGHT, LEFT;
public Direction reverse() {
Direction reverse = null;
if (this.equals(Direction.UP)) {
reverse = DOWN;
} else if (this.equals(Direction.DOWN)) {
reverse = UP;
} else if (this.equals(Direction.RIGHT)) {
reverse = LEFT;
} else if (this.equals(Direction.LEFT)) {
reverse = RIGHT;
}
return reverse;
}
};
private static final Map<String, PathNode> nodesRegistry = new TreeMap<>();
private static final RouteRegistry routeRegistry = new RouteRegistry();
private static final String keyRefDelimiter = ":";
private static final String keyRefFormat = "%d" + keyRefDelimiter + "%d";
private static PathNode destinationNode = null;
public static void main(String... arguments) {
createNodesRegistry();
findRoutes();
printSignificantRoutes();
}
private static void printSignificantRoutes() {
String shortestRoute = Arrays.toString(routeRegistry.getShortestRoute());
System.out.println("-> Shortest\t: " + shortestRoute);
String longestRoute = Arrays.toString(routeRegistry.getLongestRoute());
System.out.println("-> Longest\t: " + longestRoute);
}
private static void createNodesRegistry() {
for (int rowCount = 0; rowCount < navigableGrid.length; rowCount++) {
for (int colCount = 0; colCount < navigableGrid[rowCount].length; colCount++) {
// add current element's node representation to the nodes map, only if it is
// active (value > 0)
if (navigableGrid[rowCount][colCount] > 0) {
IntPair point = new IntPair(rowCount, colCount);
int value = navigableGrid[rowCount][colCount];
PathNode currentElementNode = new PathNode(point, value);
nodesRegistry.put(String.format(keyRefFormat, rowCount, colCount), currentElementNode);
// set adjacent references
setAdjacentReference(currentElementNode, rowCount - 1, colCount, Direction.UP);
setAdjacentReference(currentElementNode, rowCount + 1, colCount, Direction.DOWN);
setAdjacentReference(currentElementNode, rowCount, colCount + 1, Direction.RIGHT);
setAdjacentReference(currentElementNode, rowCount, colCount - 1, Direction.LEFT);
if (currentElementNode.getNodeValue() == 9) {
destinationNode = currentElementNode;
}
}
}
}
}
private static void setAdjacentReference(PathNode currentNode, int row, int col, Direction direction) {
PathNode adjacentNode = nodesRegistry.get(String.format(keyRefFormat, row, col));
if (adjacentNode != null) {
currentNode.setAdjacentNode(direction, adjacentNode);
// set the reverse lookup link
if (adjacentNode.getAdjacentNode(direction.reverse()) == null) {
adjacentNode.setAdjacentNode(direction.reverse(), currentNode);
}
}
}
private static void findRoutes() {
// initialize reverse tracing from the destination
destinationNode.traceRoute(routeRegistry, null);
}
}
class PathNode {
private int nodeValue = 0;
private Map<Direction, PathNode> adjacentNodes = new HashMap<>();
private IntPair location = null;
public PathNode() {
super();
}
public PathNode(IntPair location, int value) {
super();
this.location = location;
this.nodeValue = value;
}
public void traceRoute(RouteRegistry routeRegistry, PathNode fromNode) {
if (!this.isStartNode()) {
for (Entry<Direction, PathNode> entry : this.adjacentNodes.entrySet()) {
PathNode node = entry.getValue();
if (!node.equals(fromNode)) {
routeRegistry.put(this.location);
node.traceRoute(routeRegistry, this);
}
}
} else {
routeRegistry.put(this.location);
}
}
public int getNodeValue() {
return this.nodeValue;
}
public void setNodeValue(int value) {
this.nodeValue = value;
}
public void setAdjacentNode(Direction direction, PathNode node) {
this.adjacentNodes.put(direction, node);
}
public PathNode getAdjacentNode(Direction direction) {
return this.adjacentNodes.get(direction);
}
public IntPair getLocation() {
return location;
}
public void setLocation(IntPair location) {
this.location = location;
}
public boolean isStartNode() {
boolean returnValue = false;
if (location != null) {
returnValue = (location.getValue(0) == 0 && location.getValue(1) == 0);
}
return returnValue;
}
public boolean isDestinationNode() {
return (this.getNodeValue() == 9);
}
}
class IntPair {
private Integer[] values = new Integer[2];
public IntPair() {
super();
}
public IntPair(Integer value1, Integer value2) {
super();
this.values[0] = value1;
this.values[1] = value2;
}
public Integer getValue(int index) {
return this.values[index];
}
public void setValue(int index, int value) {
this.values[index] = value;
}
@Override
public String toString() {
return "[" + this.values[0] + ", " + this.values[1] + "]";
}
}
class RouteRegistry {
private int routeIndex = 1;
private Map <String, List<IntPair>> routesMap = new HashMap<>();
public RouteRegistry() {
super();
}
public void put(IntPair point) {
String activeRouteKey = String.format("Route %d", routeIndex);
routesMap.computeIfAbsent(activeRouteKey, k -> new ArrayList<IntPair>());
List<IntPair> routePoints = routesMap.get(activeRouteKey);
routePoints.add(point);
if (point.getValue(0) == 0 && point.getValue(1) == 0) {
routeIndex++;
}
}
public IntPair[] getShortestRoute() {
IntPair[] routeArray = null;
List<IntPair> shortestRoute = null;
for (Entry<String, List<IntPair>> routeEntry : routesMap.entrySet()) {
List<IntPair> route = routeEntry.getValue();
if (shortestRoute == null || shortestRoute.size() > route.size()) {
shortestRoute = route;
}
}
if (shortestRoute != null) {
routeArray = shortestRoute.toArray(new IntPair[shortestRoute.size()]);
} else {
routeArray = new IntPair[0];
}
return routeArray;
}
public IntPair[] getLongestRoute() {
IntPair[] routeArray = null;
List<IntPair> longestRoute = null;
for (Entry<String, List<IntPair>> routeEntry : routesMap.entrySet()) {
List<IntPair> route = routeEntry.getValue();
if (longestRoute == null || longestRoute.size() < route.size()) {
longestRoute = route;
}
}
if (longestRoute != null) {
routeArray = longestRoute.toArray(new IntPair[longestRoute.size()]);
} else {
routeArray = new IntPair[0];
}
return routeArray;
}
}
希望这有帮助-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import GridNavigationTest.Direction;
public class GridNavigationTest {
public static final int[][] navigableGrid = new int[][] {
{ 1, 1, 1, 1 },
{ 1, 0, 0, 1 },
{ 1, 0, 1, 1 },
{ 1, 0, 1, 0 },
{ 1, 1, 9, 0 }
};
public enum Direction {
UP, DOWN, RIGHT, LEFT;
public Direction reverse() {
Direction reverse = null;
if (this.equals(Direction.UP)) {
reverse = DOWN;
} else if (this.equals(Direction.DOWN)) {
reverse = UP;
} else if (this.equals(Direction.RIGHT)) {
reverse = LEFT;
} else if (this.equals(Direction.LEFT)) {
reverse = RIGHT;
}
return reverse;
}
};
private static final Map<String, PathNode> nodesRegistry = new TreeMap<>();
private static final RouteRegistry routeRegistry = new RouteRegistry();
private static final String keyRefDelimiter = ":";
private static final String keyRefFormat = "%d" + keyRefDelimiter + "%d";
private static PathNode destinationNode = null;
public static void main(String... arguments) {
createNodesRegistry();
findRoutes();
printSignificantRoutes();
}
private static void printSignificantRoutes() {
String shortestRoute = Arrays.toString(routeRegistry.getShortestRoute());
System.out.println("-> Shortest\t: " + shortestRoute);
String longestRoute = Arrays.toString(routeRegistry.getLongestRoute());
System.out.println("-> Longest\t: " + longestRoute);
}
private static void createNodesRegistry() {
for (int rowCount = 0; rowCount < navigableGrid.length; rowCount++) {
for (int colCount = 0; colCount < navigableGrid[rowCount].length; colCount++) {
// add current element's node representation to the nodes map, only if it is
// active (value > 0)
if (navigableGrid[rowCount][colCount] > 0) {
IntPair point = new IntPair(rowCount, colCount);
int value = navigableGrid[rowCount][colCount];
PathNode currentElementNode = new PathNode(point, value);
nodesRegistry.put(String.format(keyRefFormat, rowCount, colCount), currentElementNode);
// set adjacent references
setAdjacentReference(currentElementNode, rowCount - 1, colCount, Direction.UP);
setAdjacentReference(currentElementNode, rowCount + 1, colCount, Direction.DOWN);
setAdjacentReference(currentElementNode, rowCount, colCount + 1, Direction.RIGHT);
setAdjacentReference(currentElementNode, rowCount, colCount - 1, Direction.LEFT);
if (currentElementNode.getNodeValue() == 9) {
destinationNode = currentElementNode;
}
}
}
}
}
private static void setAdjacentReference(PathNode currentNode, int row, int col, Direction direction) {
PathNode adjacentNode = nodesRegistry.get(String.format(keyRefFormat, row, col));
if (adjacentNode != null) {
currentNode.setAdjacentNode(direction, adjacentNode);
// set the reverse lookup link
if (adjacentNode.getAdjacentNode(direction.reverse()) == null) {
adjacentNode.setAdjacentNode(direction.reverse(), currentNode);
}
}
}
private static void findRoutes() {
// initialize reverse tracing from the destination
destinationNode.traceRoute(routeRegistry, null);
}
}
class PathNode {
private int nodeValue = 0;
private Map<Direction, PathNode> adjacentNodes = new HashMap<>();
private IntPair location = null;
public PathNode() {
super();
}
public PathNode(IntPair location, int value) {
super();
this.location = location;
this.nodeValue = value;
}
public void traceRoute(RouteRegistry routeRegistry, PathNode fromNode) {
if (!this.isStartNode()) {
for (Entry<Direction, PathNode> entry : this.adjacentNodes.entrySet()) {
PathNode node = entry.getValue();
if (!node.equals(fromNode)) {
routeRegistry.put(this.location);
node.traceRoute(routeRegistry, this);
}
}
} else {
routeRegistry.put(this.location);
}
}
public int getNodeValue() {
return this.nodeValue;
}
public void setNodeValue(int value) {
this.nodeValue = value;
}
public void setAdjacentNode(Direction direction, PathNode node) {
this.adjacentNodes.put(direction, node);
}
public PathNode getAdjacentNode(Direction direction) {
return this.adjacentNodes.get(direction);
}
public IntPair getLocation() {
return location;
}
public void setLocation(IntPair location) {
this.location = location;
}
public boolean isStartNode() {
boolean returnValue = false;
if (location != null) {
returnValue = (location.getValue(0) == 0 && location.getValue(1) == 0);
}
return returnValue;
}
public boolean isDestinationNode() {
return (this.getNodeValue() == 9);
}
}
class IntPair {
private Integer[] values = new Integer[2];
public IntPair() {
super();
}
public IntPair(Integer value1, Integer value2) {
super();
this.values[0] = value1;
this.values[1] = value2;
}
public Integer getValue(int index) {
return this.values[index];
}
public void setValue(int index, int value) {
this.values[index] = value;
}
@Override
public String toString() {
return "[" + this.values[0] + ", " + this.values[1] + "]";
}
}
class RouteRegistry {
private int routeIndex = 1;
private Map <String, List<IntPair>> routesMap = new HashMap<>();
public RouteRegistry() {
super();
}
public void put(IntPair point) {
String activeRouteKey = String.format("Route %d", routeIndex);
routesMap.computeIfAbsent(activeRouteKey, k -> new ArrayList<IntPair>());
List<IntPair> routePoints = routesMap.get(activeRouteKey);
routePoints.add(point);
if (point.getValue(0) == 0 && point.getValue(1) == 0) {
routeIndex++;
}
}
public IntPair[] getShortestRoute() {
IntPair[] routeArray = null;
List<IntPair> shortestRoute = null;
for (Entry<String, List<IntPair>> routeEntry : routesMap.entrySet()) {
List<IntPair> route = routeEntry.getValue();
if (shortestRoute == null || shortestRoute.size() > route.size()) {
shortestRoute = route;
}
}
if (shortestRoute != null) {
routeArray = shortestRoute.toArray(new IntPair[shortestRoute.size()]);
} else {
routeArray = new IntPair[0];
}
return routeArray;
}
public IntPair[] getLongestRoute() {
IntPair[] routeArray = null;
List<IntPair> longestRoute = null;
for (Entry<String, List<IntPair>> routeEntry : routesMap.entrySet()) {
List<IntPair> route = routeEntry.getValue();
if (longestRoute == null || longestRoute.size() < route.size()) {
longestRoute = route;
}
}
if (longestRoute != null) {
routeArray = longestRoute.toArray(new IntPair[longestRoute.size()]);
} else {
routeArray = new IntPair[0];
}
return routeArray;
}
}
原则上这很好,看起来很像BFS,对吧?。您可以做一些优化:尽量避免频繁分配新内存,将访问标志存储在固定大小的列表中,而不是散列集中。有关更详细的回顾,请访问。请参阅答案。这在原则上很好,看起来很像BFS,对吗?。您可以做一些优化:尽量避免频繁分配新内存,将访问标志存储在固定大小的列表中,而不是散列集中。有关更详细的回顾,请转至。请参阅答案。虽然这可能是解决方案,但最好以某种方式解释您的方法以及它如何优于OPs源代码。此实现基本上创建了矩阵中所有节点的图形,以及它们与相邻节点的关系。此后,从目标实现BFS,直到-[1]递归的起点或[2]结束。最后,它识别最短和最长路径条目,并打印相同的条目。虽然这可能是解决方案,但最好以某种方式解释您的方法,以及它如何优于OPs源代码。此实现基本上从矩阵创建所有节点的图,以及它们与相邻节点的关系。此后,从目标实现BFS,直到-[1]递归的起点或[2]结束。最后,它识别最短和最长路径条目,并打印相同的条目。