算法题:查找矩阵中两个单元之间是否存在路径

2021年4月10日12:46:36 发表评论 833 次浏览

本文概述

给定N X N矩阵, 其中用1, 0, 2, 3填充。查找是否存在从源到目标的路径, 仅遍历空白单元格。你可以上下左右移动。

  • 单元格的值1表示来源。
  • 单元格的值2表示目的地。
  • 单元格的值3表示空白单元格。
  • 单元格的值0表示空白墙。

注意:只有一个来源和一个目的地(接收器)。

例子:

输入:M [3] [3] = {{0, 3, 2}, {3, 3, 0}, {1, 3, 0}};
输出:是
说明:输入:M [4] [4] = {{0, 3, 1, 0}, {3, 0, 3, 3}, {2, 3, 0, 3}, {0, 3 , 3, 3}};
输出:是
说明:

简单的解决方案:递归。

方法:

在每个矩阵中找到单元的源索引, 然后递归地找到从源索引到矩阵中目标的路径。该算法涉及递归查找所有路径, 直到找到到达目的地的最终路径。

算法

  1. 遍历矩阵并找到矩阵的起始索引。
  2. 创建一个采用索引和访问矩阵的递归函数。
  3. 标记当前单元格, 然后检查当前单元格是否为目的地。如果当前单元格是目的地, 则返回true。
  4. 为所有相邻的空白和未访问单元格调用递归函数。
  5. 如果任何递归函数返回true, 则取消标记该单元格并返回true, 否则取消标记该单元格并返回false。

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 boundries
     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 boundries, 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 boundries
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 boundries, 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 boundries
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 boundries, 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

输出如下:

YES

复杂度分析:

  • 时间复杂度:O(4n * m)。
    对于每个单元, 可以有4个相邻的未访问单元, 因此时间复杂度为O(4n * m)。
  • 空间复杂度:O(n * m)
    需要空间来存储访问数组。

高效的解决方案:

图形。

方法:

这个想法是使用

广度优先搜索

。将每个单元视为一个节点, 并将任何两个相邻单元之间的每个边界作为一条边。所以Node的总数是N *N。

因此, 想法是从起始单元格开始进行广度优先搜索, 直到找到终止单元格。

算法:

  1. 创建一个具有N * N个节点(顶点)的空图, 将所有节点推入图中, 并记下源顶点和宿顶点。
  2. 现在在图上应用BFS, 创建一个队列并将源节点插入该队列中
  3. 运行循环, 直到队列大小大于0
  4. 删除队列的最前面的节点, 如果目标返回true, 则检查该节点是否为目标。标记节点
  5. 检查所有相邻的单元格(如果未访问), 并将它们空白插入队列。
  6. 如果未到达目的地, 则返回true。

C ++

//C++ program to find path
//between two cell in matrix
#include <bits/stdc++.h>
using namespace std;
#define N 4
 
class Graph {
     int V;
     list<int>* adj;
 
public :
     Graph( int V)
     {
         this ->V = V;
         adj = new list<int>[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展开.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<int> queue;
 
     //Mark the current node as visited and
     //enqueue it
     visited展开 = true ;
     queue.push_back(s);
 
     //it will be used to get all adjacent
     //vertices of a vertex
     list<int>::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展开.begin(); i != adj展开.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<List<Integer>> 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<Integer> queue
             = new LinkedList<>();
 
         //Mark the current node as visited and
         //enqueue it
         visited展开 = true ;
         queue.offer(s);
 
         //it will be used to get all adjacent
         //vertices of a vertex
         List<Integer> 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展开 = 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展开:
                 
                 # 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

输出如下:

Yes

复杂度分析:

  • 时间复杂度:O(n * m)
    矩阵的每个单元仅被访问一次, 因此时间复杂度为O(n * m)。
  • 空间复杂度:O(n * m)
    需要空间来存储访问的数组并创建队列。
木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: