查找矩阵中两个单元格之间是否存在路径
给定填充有 1、0、2、3 的 NXN 矩阵。查找是否存在从源到目的地的可能路径,仅遍历空白单元格。您可以向上、向下、向右和向左移动。
- 单元格1的值表示源。
- 单元格2的值表示目的地。
- 单元格3的值表示空白单元格。
- 单元格0的值表示空白墙。
注意:只有一个源和一个目的地(接收器)。
例子:
Input:
M[3][3] = {{ 0, 3, 2 },
{ 3, 3, 0 },
{ 1, 3, 0 }};
Output : Yes
Explanation:
Input:
M[4][4] = {{ 0, 3, 1, 0 },
{ 3, 0, 3, 3 },
{ 2, 3, 0, 3 },
{ 0, 3, 3, 3 }};
Output: Yes
Explanation:
提问:Adobe 面试
简单的解决方案:递归。
方法:在每个矩阵中找到单元格的源索引,然后在矩阵中递归地找到从源索引到目标的路径。该算法涉及递归查找所有路径,直到找到到达目的地的最终路径。
算法 :
- 遍历矩阵并找到矩阵的起始索引。
- 创建一个接受索引和访问矩阵的递归函数。
- 标记当前单元格并检查当前单元格是否为目的地。如果当前单元格是目标,则返回 true。
- 为所有相邻的空单元格和未访问的单元格调用递归函数。
- 如果任何递归函数返回 true,则取消标记单元格并返回 true,否则取消标记单元格并返回 false。
C++
// C++ program to find path between two
// cell in matrix
#include
using namespace std;
#define N 4
// Method for checking boundaries
bool isSafe(int i, int j, int matrix[][N])
{
if (i >= 0 && i < N && j >= 0 && j < N)
return true;
return false;
}
// Returns true if there is a
// path from a source (a
// cell with value 1) to a
// destination (a cell with
// value 2)
bool isPath(int matrix[][N], int i, int j,
bool visited[][N])
{
// Checking the boundaries, walls and
// whether the cell is unvisited
if (isSafe(i, j, matrix) && matrix[i][j] != 0
&& !visited[i][j])
{
// Make the cell visited
visited[i][j] = true;
// if the cell is the required
// destination then return true
if (matrix[i][j] == 2)
return true;
// traverse up
bool up = isPath(matrix, i - 1, j, visited);
// if path is found in up
// direction return true
if (up)
return true;
// traverse left
bool left = isPath(matrix, i, j - 1, visited);
// if path is found in left
// direction return true
if (left)
return true;
// traverse down
bool down = isPath(matrix, i + 1, j, visited);
// if path is found in down
// direction return true
if (down)
return true;
// traverse right
bool right = isPath(matrix, i, j + 1, visited);
// if path is found in right
// direction return true
if (right)
return true;
}
// no path has been found
return false;
}
// Method for finding and printing
// whether the path exists or not
void isPath(int matrix[][N])
{
// Defining visited array to keep
// track of already visited indexes
bool visited[N][N];
// Flag to indicate whether the
// path exists or not
bool flag = false;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
// if matrix[i][j] is source
// and it is not visited
if (matrix[i][j] == 1 && !visited[i][j])
// Starting from i, j and
// then finding the path
if (isPath(matrix, i, j, visited))
{
// if path exists
flag = true;
break;
}
}
}
if (flag)
cout << "YES";
else
cout << "NO";
}
// Driver program to
// check above function
int main()
{
int matrix[N][N] = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
// calling isPath method
isPath(matrix);
return 0;
}
// This code is contributed by sudhanshugupta2019a.
Java
// Java program to find path between two
// cell in matrix
class Path {
// Method for finding and printing
// whether the path exists or not
public static void isPath(
int matrix[][], int n)
{
// Defining visited array to keep
// track of already visited indexes
boolean visited[][]
= new boolean[n][n];
// Flag to indicate whether the
// path exists or not
boolean flag = false;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// if matrix[i][j] is source
// and it is not visited
if (
matrix[i][j] == 1
&& !visited[i][j])
// Starting from i, j and
// then finding the path
if (isPath(
matrix, i, j, visited)) {
// if path exists
flag = true;
break;
}
}
}
if (flag)
System.out.println("YES");
else
System.out.println("NO");
}
// Method for checking boundaries
public static boolean isSafe(
int i, int j,
int matrix[][])
{
if (
i >= 0 && i < matrix.length
&& j >= 0
&& j < matrix[0].length)
return true;
return false;
}
// Returns true if there is a
// path from a source (a
// cell with value 1) to a
// destination (a cell with
// value 2)
public static boolean isPath(
int matrix[][],
int i, int j,
boolean visited[][])
{
// Checking the boundaries, walls and
// whether the cell is unvisited
if (
isSafe(i, j, matrix)
&& matrix[i][j] != 0
&& !visited[i][j]) {
// Make the cell visited
visited[i][j] = true;
// if the cell is the required
// destination then return true
if (matrix[i][j] == 2)
return true;
// traverse up
boolean up = isPath(
matrix, i - 1,
j, visited);
// if path is found in up
// direction return true
if (up)
return true;
// traverse left
boolean left
= isPath(
matrix, i, j - 1, visited);
// if path is found in left
// direction return true
if (left)
return true;
// traverse down
boolean down = isPath(
matrix, i + 1, j, visited);
// if path is found in down
// direction return true
if (down)
return true;
// traverse right
boolean right
= isPath(
matrix, i, j + 1,
visited);
// if path is found in right
// direction return true
if (right)
return true;
}
// no path has been found
return false;
}
// driver program to
// check above function
public static void main(String[] args)
{
int matrix[][] = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
// calling isPath method
isPath(matrix, 4);
}
}
/* This code is contributed by Madhu Priya */
Python3
# Python3 program to find
# path between two cell in matrix
# Method for finding and printing
# whether the path exists or not
def isPath(matrix, n):
# Defining visited array to keep
# track of already visited indexes
visited = [[False for x in range (n)]
for y in range (n)]
# Flag to indicate whether the
# path exists or not
flag = False
for i in range (n):
for j in range (n):
# If matrix[i][j] is source
# and it is not visited
if (matrix[i][j] == 1 and not
visited[i][j]):
# Starting from i, j and
# then finding the path
if (checkPath(matrix, i,
j, visited)):
# If path exists
flag = True
break
if (flag):
print("YES")
else:
print("NO")
# Method for checking boundaries
def isSafe(i, j, matrix):
if (i >= 0 and i < len(matrix) and
j >= 0 and j < len(matrix[0])):
return True
return False
# Returns true if there is a
# path from a source(a
# cell with value 1) to a
# destination(a cell with
# value 2)
def checkPath(matrix, i, j,
visited):
# Checking the boundaries, walls and
# whether the cell is unvisited
if (isSafe(i, j, matrix) and
matrix[i][j] != 0 and not
visited[i][j]):
# Make the cell visited
visited[i][j] = True
# If the cell is the required
# destination then return true
if (matrix[i][j] == 2):
return True
# traverse up
up = checkPath(matrix, i - 1,
j, visited)
# If path is found in up
# direction return true
if (up):
return True
# Traverse left
left = checkPath(matrix, i,
j - 1, visited)
# If path is found in left
# direction return true
if (left):
return True
# Traverse down
down = checkPath(matrix, i + 1,
j, visited)
# If path is found in down
# direction return true
if (down):
return True
# Traverse right
right = checkPath(matrix, i,
j + 1, visited)
# If path is found in right
# direction return true
if (right):
return True
# No path has been found
return False
# Driver code
if __name__ == "__main__":
matrix = [[0, 3, 0, 1],
[3, 0, 3, 3],
[2, 3, 3, 3],
[0, 3, 3, 3]]
# calling isPath method
isPath(matrix, 4)
# This code is contributed by Chitranayal
C#
// C# program to find path between two
// cell in matrix
using System;
class GFG{
// Method for finding and printing
// whether the path exists or not
static void isPath(int[,] matrix, int n)
{
// Defining visited array to keep
// track of already visited indexes
bool[,] visited = new bool[n, n];
// Flag to indicate whether the
// path exists or not
bool flag = false;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
// If matrix[i][j] is source
// and it is not visited
if (matrix[i, j] == 1 &&
!visited[i, j])
// Starting from i, j and
// then finding the path
if (isPath(matrix, i, j,
visited))
{
// If path exists
flag = true;
break;
}
}
}
if (flag)
Console.WriteLine("YES");
else
Console.WriteLine("NO");
}
// Method for checking boundaries
public static bool isSafe(int i, int j,
int[,] matrix)
{
if (i >= 0 && i < matrix.GetLength(0) &&
j >= 0 && j < matrix.GetLength(1))
return true;
return false;
}
// Returns true if there is a path from
// a source (a cell with value 1) to a
// destination (a cell with value 2)
public static bool isPath(int[,] matrix, int i,
int j, bool[,] visited)
{
// Checking the boundaries, walls and
// whether the cell is unvisited
if (isSafe(i, j, matrix) &&
matrix[i, j] != 0 &&
!visited[i, j])
{
// Make the cell visited
visited[i, j] = true;
// If the cell is the required
// destination then return true
if (matrix[i, j] == 2)
return true;
// Traverse up
bool up = isPath(matrix, i - 1,
j, visited);
// If path is found in up
// direction return true
if (up)
return true;
// Traverse left
bool left = isPath(matrix, i,
j - 1, visited);
// If path is found in left
// direction return true
if (left)
return true;
// Traverse down
bool down = isPath(matrix, i + 1,
j, visited);
// If path is found in down
// direction return true
if (down)
return true;
// Traverse right
bool right = isPath(matrix, i, j + 1,
visited);
// If path is found in right
// direction return true
if (right)
return true;
}
// No path has been found
return false;
}
// Driver code
static void Main()
{
int[,] matrix = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
// Calling isPath method
isPath(matrix, 4);
}
}
// This code is contributed by divyeshrabadiya07
Javascript
C++
// C++ program to find path
// between two cell in matrix
#include
using namespace std;
#define N 4
class Graph {
int V;
list* adj;
public:
Graph(int V)
{
this->V = V;
adj = new list[V];
}
void addEdge(int s, int d);
bool BFS(int s, int d);
};
// add edge to graph
void Graph::addEdge(int s, int d)
{
adj[s].push_back(d);
}
// BFS function to find path
// from source to sink
bool Graph::BFS(int s, int d)
{
// Base case
if (s == d)
return true;
// Mark all the vertices as not visited
bool* visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Create a queue for BFS
list queue;
// Mark the current node as visited and
// enqueue it
visited[s] = true;
queue.push_back(s);
// it will be used to get all adjacent
// vertices of a vertex
list::iterator i;
while (!queue.empty()) {
// Dequeue a vertex from queue
s = queue.front();
queue.pop_front();
// Get all adjacent vertices of the
// dequeued vertex s. If a adjacent has
// not been visited, then mark it visited
// and enqueue it
for (
i = adj[s].begin(); i != adj[s].end(); ++i) {
// If this adjacent node is the
// destination node, then return true
if (*i == d)
return true;
// Else, continue to do BFS
if (!visited[*i]) {
visited[*i] = true;
queue.push_back(*i);
}
}
}
// If BFS is complete without visiting d
return false;
}
bool isSafe(int i, int j, int M[][N])
{
if (
(i < 0 || i >= N)
|| (j < 0 || j >= N)
|| M[i][j] == 0)
return false;
return true;
}
// Returns true if there is
// a path from a source (a
// cell with value 1) to a
// destination (a cell with
// value 2)
bool findPath(int M[][N])
{
// source and destination
int s, d;
int V = N * N + 2;
Graph g(V);
// create graph with n*n node
// each cell consider as node
// Number of current vertex
int k = 1;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (M[i][j] != 0) {
// connect all 4 adjacent
// cell to current cell
if (isSafe(i, j + 1, M))
g.addEdge(k, k + 1);
if (isSafe(i, j - 1, M))
g.addEdge(k, k - 1);
if (i < N - 1 && isSafe(i + 1, j, M))
g.addEdge(k, k + N);
if (i > 0 && isSafe(i - 1, j, M))
g.addEdge(k, k - N);
}
// Source index
if (M[i][j] == 1)
s = k;
// Destination index
if (M[i][j] == 2)
d = k;
k++;
}
}
// find path Using BFS
return g.BFS(s, d);
}
// driver program to check
// above function
int main()
{
int M[N][N] = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
(findPath(M) == true) ? cout << "Yes" : cout << "No" << endl;
return 0;
}
Java
// Java program to find path between two
// cell in matrix
import java.util.*;
class Graph {
int V;
List > adj;
Graph(int V)
{
this.V = V;
adj = new ArrayList<>(V);
for (int i = 0; i < V; i++) {
adj.add(i, new ArrayList<>());
}
}
// add edge to graph
void addEdge(int s, int d)
{
adj.get(s).add(d);
}
// BFS function to find path
// from source to sink
boolean BFS(int s, int d)
{
// Base case
if (s == d)
return true;
// Mark all the vertices as not visited
boolean[] visited = new boolean[V];
// Create a queue for BFS
Queue queue
= new LinkedList<>();
// Mark the current node as visited and
// enqueue it
visited[s] = true;
queue.offer(s);
// it will be used to get all adjacent
// vertices of a vertex
List edges;
while (!queue.isEmpty()) {
// Dequeue a vertex from queue
s = queue.poll();
// Get all adjacent vertices of the
// dequeued vertex s. If a adjacent has
// not been visited, then mark it visited
// and enqueue it
edges = adj.get(s);
for (int curr : edges) {
// If this adjacent node is the
// destination node, then return true
if (curr == d)
return true;
// Else, continue to do BFS
if (!visited[curr]) {
visited[curr] = true;
queue.offer(curr);
}
}
}
// If BFS is complete without visiting d
return false;
}
static boolean isSafe(
int i, int j, int[][] M)
{
int N = M.length;
if (
(i < 0 || i >= N)
|| (j < 0 || j >= N)
|| M[i][j] == 0)
return false;
return true;
}
// Returns true if there is a
// path from a source (a
// cell with value 1) to a
// destination (a cell with
// value 2)
static boolean findPath(int[][] M)
{
// Source and destination
int s = -1, d = -1;
int N = M.length;
int V = N * N + 2;
Graph g = new Graph(V);
// Create graph with n*n node
// each cell consider as node
int k = 1; // Number of current vertex
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (M[i][j] != 0) {
// connect all 4 adjacent
// cell to current cell
if (isSafe(i, j + 1, M))
g.addEdge(k, k + 1);
if (isSafe(i, j - 1, M))
g.addEdge(k, k - 1);
if (i < N - 1
&& isSafe(i + 1, j, M))
g.addEdge(k, k + N);
if (i > 0 && isSafe(i - 1, j, M))
g.addEdge(k, k - N);
}
// source index
if (M[i][j] == 1)
s = k;
// destination index
if (M[i][j] == 2)
d = k;
k++;
}
}
// find path Using BFS
return g.BFS(s, d);
}
// Driver program to check above function
public static void main(
String[] args) throws Exception
{
int[][] M = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
System.out.println(
((findPath(M)) ? "Yes" : "No"));
}
}
// This code is contributed by abhay379201
Python3
# Python3 program to find path between two
# cell in matrix
from collections import defaultdict
class Graph:
def __init__(self):
self.graph = defaultdict(list)
# add edge to graph
def addEdge(self, u, v):
self.graph[u].append(v)
# BFS function to find path from source to sink
def BFS(self, s, d):
# Base case
if s == d:
return True
# Mark all the vertices as not visited
visited = [False]*(len(self.graph) + 1)
# Create a queue for BFS
queue = []
queue.append(s)
# Mark the current node as visited and
# enqueue it
visited[s] = True
while(queue):
# Dequeue a vertex from queue
s = queue.pop(0)
# Get all adjacent vertices of the
# dequeued vertex s. If a adjacent has
# not been visited, then mark it visited
# and enqueue it
for i in self.graph[s]:
# If this adjacent node is the destination
# node, then return true
if i == d:
return True
# Else, continue to do BFS
if visited[i] == False:
queue.append(i)
visited[i] = True
# If BFS is complete without visiting d
return False
def isSafe(i, j, matrix):
if i >= 0 and i <= len(matrix) and j >= 0 and j <= len(matrix[0]):
return True
else:
return False
# Returns true if there is a path from a source (a
# cell with value 1) to a destination (a cell with
# value 2)
def findPath(M):
s, d = None, None # source and destination
N = len(M)
g = Graph()
# create graph with n * n node
# each cell consider as node
k = 1 # Number of current vertex
for i in range(N):
for j in range(N):
if (M[i][j] != 0):
# connect all 4 adjacent cell to
# current cell
if (isSafe(i, j + 1, M)):
g.addEdge(k, k + 1)
if (isSafe(i, j - 1, M)):
g.addEdge(k, k - 1)
if (isSafe(i + 1, j, M)):
g.addEdge(k, k + N)
if (isSafe(i - 1, j, M)):
g.addEdge(k, k - N)
if (M[i][j] == 1):
s = k
# destination index
if (M[i][j] == 2):
d = k
k += 1
# find path Using BFS
return g.BFS(s, d)
# Driver code
if __name__=='__main__':
M =[[0, 3, 0, 1], [3, 0, 3, 3], [2, 3, 3, 3], [0, 3, 3, 3]]
if findPath(M):
print("Yes")
else:
print("No")
# This Code is Contributed by Vikash Kumar 37
Javascript
C++
#include
#include
using namespace std;
#define R 4
#define C 4
// Structure to define a vertex u=(i,j)
typedef struct BFSElement {
BFSElement(int i, int j)
{
this->i = i;
this->j = j;
}
int i;
int j;
} BFSElement;
bool findPath(int M[R][C])
{
// 1) Create BFS queue q
queue q;
// 2)scan the matrix
for (int i = 0; i < R; ++i) {
for (int j = 0; j < C; ++j) {
// if there exists a cell in the matrix such
// that its value is 1 then push it to q
if (M[i][j] == 1) {
q.push(BFSElement(i, j));
break;
}
}
}
// 3) run BFS algorithm with q.
while (!q.empty()) {
BFSElement x = q.front();
q.pop();
int i = x.i;
int j = x.j;
// skipping cells which are not valid.
// if outside the matrix bounds
if (i < 0 || i > R || j < 0 || j > C)
continue;
// if they are walls (value is 0).
if (M[i][j] == 0)
continue;
// 3.1) if in the BFS algorithm process there was a
// vertex x=(i,j) such that M[i][j] is 2 stop and
// return true
if (M[i][j] == 2)
return true;
// marking as wall upon successful visitation
M[i][j] = 0;
// pushing to queue u=(i,j+1),u=(i,j-1)
// u=(i+1,j),u=(i-1,j)
for (int k = -1; k <= 1; k += 2) {
q.push(BFSElement(i + k, j));
q.push(BFSElement(i, j + k));
}
}
// BFS algorithm terminated without returning true
// then there was no element M[i][j] which is 2, then
// return false
return false;
}
// Main Driver code
int main()
{
int M[R][C] = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
(findPath(M) == true) ? cout << "Yes"
: cout << "No" << endl;
return 0;
}
Java
import java.io.*;
import java.util.*;
class BFSElement
{
int i, j;
BFSElement(int i, int j)
{
this.i = i;
this.j = j;
}
}
class GFG {
static int R = 4, C = 4;
BFSElement b;
static boolean findPath(int M[][])
{
// 1) Create BFS queue q
Queue q = new LinkedList<>();
// 2)scan the matrix
for (int i = 0; i < R; ++i)
{
for (int j = 0; j < C; ++j)
{
// if there exists a cell in the matrix such
// that its value is 1 then push it to q
if (M[i][j] == 1) {
q.add(new BFSElement(i, j));
break;
}
}
}
// 3) run BFS algorithm with q.
while (q.size() != 0)
{
BFSElement x = q.peek();
q.remove();
int i = x.i;
int j = x.j;
// skipping cells which are not valid.
// if outside the matrix bounds
if (i < 0 || i >= R || j < 0 || j >= C)
continue;
// if they are walls (value is 0).
if (M[i][j] == 0)
continue;
// 3.1) if in the BFS algorithm process there was a
// vertex x=(i,j) such that M[i][j] is 2 stop and
// return true
if (M[i][j] == 2)
return true;
// marking as wall upon successful visitation
M[i][j] = 0;
// pushing to queue u=(i,j+1),u=(i,j-1)
// u=(i+1,j),u=(i-1,j)
for (int k = -1; k <= 1; k += 2)
{
q.add(new BFSElement(i + k, j));
q.add(new BFSElement(i, j + k));
}
}
// BFS algorithm terminated without returning true
// then there was no element M[i][j] which is 2, then
// return false
return false;
}
// Main Driver code
public static void main (String[] args)
{
int M[][] = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
if(findPath(M) == true)
System.out.println("Yes");
else
System.out.println("No");
}
}
// This code is contributed by avanitrachhadiya2155
C#
using System;
using System.Collections.Generic;
public class BFSElement
{
public int i, j;
public BFSElement(int i, int j)
{
this.i = i;
this.j = j;
}
}
public class GFG
{
static int R = 4, C = 4;
static bool findPath(int[,] M)
{
// 1) Create BFS queue q
Queue q = new Queue();
// 2)scan the matrix
for (int i = 0; i < R; ++i)
{
for (int j = 0; j < C; ++j)
{
// if there exists a cell in the matrix such
// that its value is 1 then push it to q
if (M[i, j] == 1) {
q.Enqueue(new BFSElement(i, j));
break;
}
}
}
// 3) run BFS algorithm with q.
while (q.Count != 0)
{
BFSElement x = q.Peek();
q.Dequeue();
int i = x.i;
int j = x.j;
// skipping cells which are not valid.
// if outside the matrix bounds
if (i < 0 || i >= R || j < 0 || j >= C)
continue;
// if they are walls (value is 0).
if (M[i, j] == 0)
continue;
// 3.1) if in the BFS algorithm process there was a
// vertex x=(i,j) such that M[i][j] is 2 stop and
// return true
if (M[i, j] == 2)
return true;
// marking as wall upon successful visitation
M[i, j] = 0;
// pushing to queue u=(i,j+1),u=(i,j-1)
// u=(i+1,j),u=(i-1,j)
for (int k = -1; k <= 1; k += 2)
{
q.Enqueue(new BFSElement(i + k, j));
q.Enqueue(new BFSElement(i, j + k));
}
}
// BFS algorithm terminated without returning true
// then there was no element M[i][j] which is 2, then
// return false
return false;
}
// Main Driver code
static public void Main (){
int[,] M = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
if(findPath(M) == true)
Console.WriteLine("Yes");
else
Console.WriteLine("No");
}
}
// This code is contributed by rag2127
Javascript
YES
复杂性分析:
- 时间复杂度: O(4 n*m )。
对于每个单元格,可以有 4 个相邻的未访问单元格,因此时间复杂度为 O(4 n*m )。 - 空间复杂度: O(n*m)。
存储访问的数组需要空间。
有效的解决方案:图表。
方法:这个想法是使用广度优先搜索。将每个单元格视为一个节点,任何两个相邻单元格之间的每个边界都是一条边。所以Node的总数是N * N。
所以想法是从起始单元格开始进行广度优先搜索,直到找到结束单元格。
算法:
- 创建一个具有 N*N 节点(顶点)的空 Graph,将所有节点推入一个图中,并记下源和汇顶点。
- 现在在图上应用 BFS,创建一个队列并将源节点插入队列中
- 循环运行直到队列的大小大于 0
- 移除队列的前端节点,如果destination返回true,则检查该节点是否为destination。标记节点
- 如果未访问,则检查所有相邻单元格,并将它们空白插入队列中。
- 如果未到达目的地,则返回 true。
C++
// C++ program to find path
// between two cell in matrix
#include
using namespace std;
#define N 4
class Graph {
int V;
list* adj;
public:
Graph(int V)
{
this->V = V;
adj = new list[V];
}
void addEdge(int s, int d);
bool BFS(int s, int d);
};
// add edge to graph
void Graph::addEdge(int s, int d)
{
adj[s].push_back(d);
}
// BFS function to find path
// from source to sink
bool Graph::BFS(int s, int d)
{
// Base case
if (s == d)
return true;
// Mark all the vertices as not visited
bool* visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Create a queue for BFS
list queue;
// Mark the current node as visited and
// enqueue it
visited[s] = true;
queue.push_back(s);
// it will be used to get all adjacent
// vertices of a vertex
list::iterator i;
while (!queue.empty()) {
// Dequeue a vertex from queue
s = queue.front();
queue.pop_front();
// Get all adjacent vertices of the
// dequeued vertex s. If a adjacent has
// not been visited, then mark it visited
// and enqueue it
for (
i = adj[s].begin(); i != adj[s].end(); ++i) {
// If this adjacent node is the
// destination node, then return true
if (*i == d)
return true;
// Else, continue to do BFS
if (!visited[*i]) {
visited[*i] = true;
queue.push_back(*i);
}
}
}
// If BFS is complete without visiting d
return false;
}
bool isSafe(int i, int j, int M[][N])
{
if (
(i < 0 || i >= N)
|| (j < 0 || j >= N)
|| M[i][j] == 0)
return false;
return true;
}
// Returns true if there is
// a path from a source (a
// cell with value 1) to a
// destination (a cell with
// value 2)
bool findPath(int M[][N])
{
// source and destination
int s, d;
int V = N * N + 2;
Graph g(V);
// create graph with n*n node
// each cell consider as node
// Number of current vertex
int k = 1;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (M[i][j] != 0) {
// connect all 4 adjacent
// cell to current cell
if (isSafe(i, j + 1, M))
g.addEdge(k, k + 1);
if (isSafe(i, j - 1, M))
g.addEdge(k, k - 1);
if (i < N - 1 && isSafe(i + 1, j, M))
g.addEdge(k, k + N);
if (i > 0 && isSafe(i - 1, j, M))
g.addEdge(k, k - N);
}
// Source index
if (M[i][j] == 1)
s = k;
// Destination index
if (M[i][j] == 2)
d = k;
k++;
}
}
// find path Using BFS
return g.BFS(s, d);
}
// driver program to check
// above function
int main()
{
int M[N][N] = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
(findPath(M) == true) ? cout << "Yes" : cout << "No" << endl;
return 0;
}
Java
// Java program to find path between two
// cell in matrix
import java.util.*;
class Graph {
int V;
List > adj;
Graph(int V)
{
this.V = V;
adj = new ArrayList<>(V);
for (int i = 0; i < V; i++) {
adj.add(i, new ArrayList<>());
}
}
// add edge to graph
void addEdge(int s, int d)
{
adj.get(s).add(d);
}
// BFS function to find path
// from source to sink
boolean BFS(int s, int d)
{
// Base case
if (s == d)
return true;
// Mark all the vertices as not visited
boolean[] visited = new boolean[V];
// Create a queue for BFS
Queue queue
= new LinkedList<>();
// Mark the current node as visited and
// enqueue it
visited[s] = true;
queue.offer(s);
// it will be used to get all adjacent
// vertices of a vertex
List edges;
while (!queue.isEmpty()) {
// Dequeue a vertex from queue
s = queue.poll();
// Get all adjacent vertices of the
// dequeued vertex s. If a adjacent has
// not been visited, then mark it visited
// and enqueue it
edges = adj.get(s);
for (int curr : edges) {
// If this adjacent node is the
// destination node, then return true
if (curr == d)
return true;
// Else, continue to do BFS
if (!visited[curr]) {
visited[curr] = true;
queue.offer(curr);
}
}
}
// If BFS is complete without visiting d
return false;
}
static boolean isSafe(
int i, int j, int[][] M)
{
int N = M.length;
if (
(i < 0 || i >= N)
|| (j < 0 || j >= N)
|| M[i][j] == 0)
return false;
return true;
}
// Returns true if there is a
// path from a source (a
// cell with value 1) to a
// destination (a cell with
// value 2)
static boolean findPath(int[][] M)
{
// Source and destination
int s = -1, d = -1;
int N = M.length;
int V = N * N + 2;
Graph g = new Graph(V);
// Create graph with n*n node
// each cell consider as node
int k = 1; // Number of current vertex
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (M[i][j] != 0) {
// connect all 4 adjacent
// cell to current cell
if (isSafe(i, j + 1, M))
g.addEdge(k, k + 1);
if (isSafe(i, j - 1, M))
g.addEdge(k, k - 1);
if (i < N - 1
&& isSafe(i + 1, j, M))
g.addEdge(k, k + N);
if (i > 0 && isSafe(i - 1, j, M))
g.addEdge(k, k - N);
}
// source index
if (M[i][j] == 1)
s = k;
// destination index
if (M[i][j] == 2)
d = k;
k++;
}
}
// find path Using BFS
return g.BFS(s, d);
}
// Driver program to check above function
public static void main(
String[] args) throws Exception
{
int[][] M = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
System.out.println(
((findPath(M)) ? "Yes" : "No"));
}
}
// This code is contributed by abhay379201
Python3
# Python3 program to find path between two
# cell in matrix
from collections import defaultdict
class Graph:
def __init__(self):
self.graph = defaultdict(list)
# add edge to graph
def addEdge(self, u, v):
self.graph[u].append(v)
# BFS function to find path from source to sink
def BFS(self, s, d):
# Base case
if s == d:
return True
# Mark all the vertices as not visited
visited = [False]*(len(self.graph) + 1)
# Create a queue for BFS
queue = []
queue.append(s)
# Mark the current node as visited and
# enqueue it
visited[s] = True
while(queue):
# Dequeue a vertex from queue
s = queue.pop(0)
# Get all adjacent vertices of the
# dequeued vertex s. If a adjacent has
# not been visited, then mark it visited
# and enqueue it
for i in self.graph[s]:
# If this adjacent node is the destination
# node, then return true
if i == d:
return True
# Else, continue to do BFS
if visited[i] == False:
queue.append(i)
visited[i] = True
# If BFS is complete without visiting d
return False
def isSafe(i, j, matrix):
if i >= 0 and i <= len(matrix) and j >= 0 and j <= len(matrix[0]):
return True
else:
return False
# Returns true if there is a path from a source (a
# cell with value 1) to a destination (a cell with
# value 2)
def findPath(M):
s, d = None, None # source and destination
N = len(M)
g = Graph()
# create graph with n * n node
# each cell consider as node
k = 1 # Number of current vertex
for i in range(N):
for j in range(N):
if (M[i][j] != 0):
# connect all 4 adjacent cell to
# current cell
if (isSafe(i, j + 1, M)):
g.addEdge(k, k + 1)
if (isSafe(i, j - 1, M)):
g.addEdge(k, k - 1)
if (isSafe(i + 1, j, M)):
g.addEdge(k, k + N)
if (isSafe(i - 1, j, M)):
g.addEdge(k, k - N)
if (M[i][j] == 1):
s = k
# destination index
if (M[i][j] == 2):
d = k
k += 1
# find path Using BFS
return g.BFS(s, d)
# Driver code
if __name__=='__main__':
M =[[0, 3, 0, 1], [3, 0, 3, 3], [2, 3, 3, 3], [0, 3, 3, 3]]
if findPath(M):
print("Yes")
else:
print("No")
# This Code is Contributed by Vikash Kumar 37
Javascript
Yes
复杂性分析:
- 时间复杂度: O(n*m)。
矩阵的每个单元只被访问一次,因此时间复杂度为 O(n*m)。 - 空间复杂度: O(n*m)。
存储访问过的数组和创建队列需要空间。
简单有效的解决方案:图形本身就是矩阵。
方法:这个想法是在矩阵本身上使用广度优先搜索。
将 cell=(i,j) 视为 BFS 队列中的顶点 v。如果 u=(i+1,j) 或 u=(i-1,j) 或 u=(i,j+1) 或 u=(i,j-1) 则将新顶点 u 放入 BFS 队列.从 cell=(i,j) 开始 BFS 算法,使得 M[i][j] 为 1,如果存在可达顶点 u=(i,j) 使得 M[i][j] 为 2,则停止并返回 true 或每个单元格都被覆盖,并且没有这样的单元格并返回 false。
算法:
1) 创建 BFS 队列 q
2)扫描矩阵,如果矩阵中存在一个单元格,其值为1,则将其推送到q
3) 使用 q 运行 BFS 算法,跳过无效的单元格。即:它们是墙壁(值为0)或在矩阵边界之外,并在成功访问时将它们标记为墙壁。
3.1) 如果在BFS算法过程中有一个顶点x=(i,j)使得M[i][j]是2 停止并返回true
4) BFS 算法终止且不返回 true 则没有元素 M[i][j] 为 2,则返回 false
C++
#include
#include
using namespace std;
#define R 4
#define C 4
// Structure to define a vertex u=(i,j)
typedef struct BFSElement {
BFSElement(int i, int j)
{
this->i = i;
this->j = j;
}
int i;
int j;
} BFSElement;
bool findPath(int M[R][C])
{
// 1) Create BFS queue q
queue q;
// 2)scan the matrix
for (int i = 0; i < R; ++i) {
for (int j = 0; j < C; ++j) {
// if there exists a cell in the matrix such
// that its value is 1 then push it to q
if (M[i][j] == 1) {
q.push(BFSElement(i, j));
break;
}
}
}
// 3) run BFS algorithm with q.
while (!q.empty()) {
BFSElement x = q.front();
q.pop();
int i = x.i;
int j = x.j;
// skipping cells which are not valid.
// if outside the matrix bounds
if (i < 0 || i > R || j < 0 || j > C)
continue;
// if they are walls (value is 0).
if (M[i][j] == 0)
continue;
// 3.1) if in the BFS algorithm process there was a
// vertex x=(i,j) such that M[i][j] is 2 stop and
// return true
if (M[i][j] == 2)
return true;
// marking as wall upon successful visitation
M[i][j] = 0;
// pushing to queue u=(i,j+1),u=(i,j-1)
// u=(i+1,j),u=(i-1,j)
for (int k = -1; k <= 1; k += 2) {
q.push(BFSElement(i + k, j));
q.push(BFSElement(i, j + k));
}
}
// BFS algorithm terminated without returning true
// then there was no element M[i][j] which is 2, then
// return false
return false;
}
// Main Driver code
int main()
{
int M[R][C] = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
(findPath(M) == true) ? cout << "Yes"
: cout << "No" << endl;
return 0;
}
Java
import java.io.*;
import java.util.*;
class BFSElement
{
int i, j;
BFSElement(int i, int j)
{
this.i = i;
this.j = j;
}
}
class GFG {
static int R = 4, C = 4;
BFSElement b;
static boolean findPath(int M[][])
{
// 1) Create BFS queue q
Queue q = new LinkedList<>();
// 2)scan the matrix
for (int i = 0; i < R; ++i)
{
for (int j = 0; j < C; ++j)
{
// if there exists a cell in the matrix such
// that its value is 1 then push it to q
if (M[i][j] == 1) {
q.add(new BFSElement(i, j));
break;
}
}
}
// 3) run BFS algorithm with q.
while (q.size() != 0)
{
BFSElement x = q.peek();
q.remove();
int i = x.i;
int j = x.j;
// skipping cells which are not valid.
// if outside the matrix bounds
if (i < 0 || i >= R || j < 0 || j >= C)
continue;
// if they are walls (value is 0).
if (M[i][j] == 0)
continue;
// 3.1) if in the BFS algorithm process there was a
// vertex x=(i,j) such that M[i][j] is 2 stop and
// return true
if (M[i][j] == 2)
return true;
// marking as wall upon successful visitation
M[i][j] = 0;
// pushing to queue u=(i,j+1),u=(i,j-1)
// u=(i+1,j),u=(i-1,j)
for (int k = -1; k <= 1; k += 2)
{
q.add(new BFSElement(i + k, j));
q.add(new BFSElement(i, j + k));
}
}
// BFS algorithm terminated without returning true
// then there was no element M[i][j] which is 2, then
// return false
return false;
}
// Main Driver code
public static void main (String[] args)
{
int M[][] = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
if(findPath(M) == true)
System.out.println("Yes");
else
System.out.println("No");
}
}
// This code is contributed by avanitrachhadiya2155
C#
using System;
using System.Collections.Generic;
public class BFSElement
{
public int i, j;
public BFSElement(int i, int j)
{
this.i = i;
this.j = j;
}
}
public class GFG
{
static int R = 4, C = 4;
static bool findPath(int[,] M)
{
// 1) Create BFS queue q
Queue q = new Queue();
// 2)scan the matrix
for (int i = 0; i < R; ++i)
{
for (int j = 0; j < C; ++j)
{
// if there exists a cell in the matrix such
// that its value is 1 then push it to q
if (M[i, j] == 1) {
q.Enqueue(new BFSElement(i, j));
break;
}
}
}
// 3) run BFS algorithm with q.
while (q.Count != 0)
{
BFSElement x = q.Peek();
q.Dequeue();
int i = x.i;
int j = x.j;
// skipping cells which are not valid.
// if outside the matrix bounds
if (i < 0 || i >= R || j < 0 || j >= C)
continue;
// if they are walls (value is 0).
if (M[i, j] == 0)
continue;
// 3.1) if in the BFS algorithm process there was a
// vertex x=(i,j) such that M[i][j] is 2 stop and
// return true
if (M[i, j] == 2)
return true;
// marking as wall upon successful visitation
M[i, j] = 0;
// pushing to queue u=(i,j+1),u=(i,j-1)
// u=(i+1,j),u=(i-1,j)
for (int k = -1; k <= 1; k += 2)
{
q.Enqueue(new BFSElement(i + k, j));
q.Enqueue(new BFSElement(i, j + k));
}
}
// BFS algorithm terminated without returning true
// then there was no element M[i][j] which is 2, then
// return false
return false;
}
// Main Driver code
static public void Main (){
int[,] M = { { 0, 3, 0, 1 },
{ 3, 0, 3, 3 },
{ 2, 3, 3, 3 },
{ 0, 3, 3, 3 } };
if(findPath(M) == true)
Console.WriteLine("Yes");
else
Console.WriteLine("No");
}
}
// This code is contributed by rag2127
Javascript
Yes
时间复杂度:O(n*m)。
空间复杂度:O(n*m)。
改进由 Ephi F.