Question
Given a matrix M of size NxM with integer values 1,2,3, and 4, each value represents the only possible movement from that cell.
1 -> move left 2 -> move right 3 -> move up 4 -> move down. |
Return minimum possible changes required in the matrix such that a path exists from (0, 0) to (N-1, M-1).
Alert Ninjas: Don’t stop now! Enroll in the Competitive Programming course today and start coding. Learn the art of writing time and space-efficient code and compete in code competitions worldwide.
Example 1:
Input: M = {{2, 2, 4},
Explanation: |
Example 2:
Input: M = {{2, 2, 1},
|
Recommended: Please try to solve it yourself first before moving on to the solution.
Solution
Method 1
Consider each cell of the 2D matrix to be a node in the weighted graph, with each node having a maximum of four connected nodes (possible four directions). Each edge weights as follows:
If the movement of node U is in the direction of V, weight(U, V) = 0, else weight(U, V) = 1. |
Now, the problem reduces to finding the shortest path in a weighted graph, which can be computed using Djikstra’s Algorithm.
Implementation
C++ code
#include <bits/stdc++.h> // adding a node in the graph by going down. |
Output
Time Complexity: O( N * M * log( N * M ) )
Space Complexity: O( N * M )
Method 2
Reduce the given problem to find the shortest path in a weighted graph as done in method 1. Now, edge weights are 0 and 1 only, i.e., a 0-1 graph. The shortest path in 0-1 graphs can be found using 0-1 BFS.
Click here to learn more about 0-1 BFS.
Implementation
C++ code
#include <bits/stdc++.h> using namespace std; int zeroOneBFS(vector<pair<int, int> >* adj, int n, int m, int src, int dest,) { // to store the distance. vector<int> distance( n*m, INT_MAX); // Double ended queue to do BFS. deque<int> q; distance[src] = 0; q.push_back(src); while (!q.empty()) { int u = q.front(); q.pop_front(); for (auto i : adj[u]) { // Checking for the optimal distance. if (distance[i.first] > distance[u] + i.second) { distance[i.first] = distance[u]+ i.second; //Put 0 weight edges to front and 1 weight edges to back to //to process vertices in increasing order of weights. if (i.second == 0) q.push_front(i.first); else q.push_back(i.first); } } } return distance[dest]; } int MinModifications(vector<vector<int> >& M) { int n = M.size(); int m = M[0].size(); // Converting given matrix to a weighted graph. vector<pair<int, int> > adj[n*m]; for (int i = 0; i <= n-1; i++) { for (int j = 0; j <= m-1; j++) { // Each cell in M is a node with label i*n + j. // adding a node in the graph by going down. if( i+1 < n){ // if the direction is the same as stated in the given cell, keep the //weight of the edge 0. if( M[i][j] == 4) adj[i * n + j].push_back({(i+1)*n + j, 0 }); else adj[i * n + j].push_back({(i+1)*n + j, 1 }); } // adding a node in the graph by going up. if( i-1 >= 0){ if( M[i][j] == 3) adj[i * n + j].push_back({(i-1)*n + j, 0 }); else adj[i * n + j].push_back({(i-1)*n + j, 1 }); } // going left. if( j-1 >= 0){ if( M[i][j] == 1) adj[i * n + j].push_back({i*n + (j-1), 0 }); else adj[i * n + j].push_back({i*n + (j-1), 1 }); } // going right if( j+1 < m){ if( M[i][j] == 2) adj[i * n + j].push_back({i*n + (j+1), 0 }); else adj[i * n + j].push_back({i*n + (j+1), 1 }); } } } return zeroOneBFS(adj, n, m, 0, (n-1) * n + m - 1); } // Driver code int main() { vector<vector<int> > mat = { { 2, 2, 1 }, { 4, 2, 3 }, { 4, 3, 2 } }; cout << "\n "<<MinModifications(mat); return 0; } |
Output
Time complexity from this method: O(N * M)
Space complexity: O(N * M)
Check out this problem - Matrix Median