Given a Grid of size NxM, and two integers X and Y, the task is to count the minimum number of rows between the row containing X and the row containing Y in such a way that the adjacent rows in between them have at least one element in common. Multiple occurrences of a number are allowed in the grid. In other words, two rows are said to be adjacent if they have at least one element in common.
Examples:
Input: arr[][] = {{1, 2, 3}, {2, 5, 6}, {7, 8, 13}}, X = 1, Y = 6
Output: 0
Explanation: X = 1 is present in row 0 (considering 0 – indexing) and Y = 6 is in row 2.
Both the rows have ‘2’ in common both of them are adjacent and there are 0 rows in between.Input: arr[][] = {{1, 2, 3}, {2, 5, 6}, {3, 7, 13}}, X = 2, Y = 6
Output: 0
Explanation: Both the numbers are in same row.Input: arr[][] = {{1, 2, 3}, {2, 5, 6}, {3, 7, 13}}, X = 2, Y = 8
Output: -1
Explanation: There is no possible combination of adjacent rows between row containing X and row containing Y.Input: arr[][] = {{1, 2, 3, 21}, {1, 11, 12, 25}, {12, 13, 14, 7}, {3, 5, 6, 7}, {6, 8, 9, 10}}, X = 1, Y = 9
Output: 1
Explanation: One possible combination of adjacent rows is 0 -> 1 -> 2 -> 3 -> 4 which has 3 adjacent rows between them.
Another possible way 1 -> 2 -> 3 -> 4 which has 2 adjacent rows between them.
The path which have minimum rows would be 0 -> 4 -> 5 which has only 1 row in-between.
Approach: The given problem can be solved by using the shortest path in an unweighted graph that uses BFS Algorithm.
- Create an unweighted graph where each node represents a row.
- Two nodes of this graph are connected if they share at least 1 common number between them.
- Run outer for loop from i = 0 to N where N is the number of rows.
- Run an inner loop from j = i + 1 to N .
- Connect row ‘i’ and row ‘j’ if there is something common in both rows.
- Run outer for loop from i = 0 to N where N is the number of rows.
- Now the problem is reduced to finding the shortest path from the node having X to the node having Y.
- Again run another nested loop and store the rows which have X in a queue to be used for BFS.
- Also, storing all the rows which have Y, it will be used to detect if the node has target number is reached or not.
- If the current node in the BFS traversal of the graph has a Y, return the number of edges traveled – 1.
- If BFS is over return -1 as there is no possible combination of adjacent rows between both rows.
Below is the implementation of the above approach:
// C++ program to implement the approach #include <bits/stdc++.h> using namespace std;
// class to represent node in queue class Node {
public :
int rowNo;
int edgesTravelled;
Node( int r, int e)
{
this ->rowNo = r;
this ->edgesTravelled = e;
}
}; // function to check connection b/w two rows bool shareCommon(vector< int >& i, vector< int >& j)
{ // adding all elements of larger array to hashset then
// iterating other array
set< int > row1;
if (i.size() > j.size()) {
for ( int idx = 0; idx < i.size(); idx++) {
row1.insert(i[idx]);
}
for ( int idx = 0; idx < j.size(); idx++) {
if (row1.count(j[idx]))
return true ;
}
}
else {
for ( int idx = 0; idx < j.size(); idx++) {
row1.insert(j[idx]);
}
for ( int idx = 0; idx < i.size(); idx++) {
if (row1.count(i[idx]))
return true ;
}
}
return false ;
} void minRowsBetweenXY(vector<vector< int > >& arr, int X,
int Y)
{ // No. of rows
int N = arr.size();
if (X == Y) {
cout << 0;
return ;
}
// constructing graph:
vector<vector< int > > graph(N);
for ( int i = 0; i < N; i++) {
for ( int j = i + 1; j < N; j++) {
// if row i and j share something in common then
// connect row i and j
if (shareCommon(arr[i], arr[j])) {
graph[i].push_back(j);
graph[j].push_back(i);
}
}
}
// queue for BFS
queue<Node> q;
// visited array for bfs
vector< bool > visited(N, false );
// Set to store rows having Y
set< int > targetRows;
for ( int i = 0; i < N; i++) {
for ( int j = 0; j < arr[i].size(); j++) {
if (arr[i][j] == Y) {
targetRows.insert(i);
}
if (arr[i][j] == X && !visited[i]) {
q.push(Node(i, 0));
// q.add(new Node(i, 0));
visited[i] = true ;
}
}
}
// using bfs algorithm:
while (q.size() > 0) {
Node rm = q.front();
q.pop();
// if the removed node is in the target row then
// return
if (targetRows.count(rm.rowNo)) {
if (rm.edgesTravelled == 0) {
cout << 0;
return ;
}
cout << rm.edgesTravelled - 1;
return ;
}
// adding neighbouring nodes
for ( int nbr : graph[rm.rowNo]) {
if (!visited[nbr]) {
int edgesTravelledBeforeNbr
= rm.edgesTravelled;
q.push(
Node(nbr, 1 + edgesTravelledBeforeNbr));
visited[nbr] = true ;
}
}
}
// if bfs over => path not possible
cout << -1;
} // Driver code int main()
{ vector<vector< int > > arr = { { 1, 2, 3, 21 },
{ 1, 11, 12, 25 },
{ 12, 13, 14, 7 },
{ 3, 5, 6, 7 },
{ 6, 8, 9, 10 } };
int X = 1;
int Y = 9;
minRowsBetweenXY(arr, X, Y);
return 0;
} // This code is contributed by abhishekghoshindia. |
// Java program to find minimum adjacent // rows between rows containing X and Y import java.util.*;
class GFG {
static void minRowsBetweenXY( int [][] arr,
int X, int Y)
{
// No. of rows
int N = arr.length;
if (X == Y) {
System.out.println( 0 );
return ;
}
// constructing graph:
ArrayList<ArrayList<Integer> > graph
= new ArrayList<ArrayList<Integer> >();
for ( int i = 0 ; i < N; i++) {
graph.add( new ArrayList<>());
}
for ( int i = 0 ; i < N; i++) {
for ( int j = i + 1 ; j < N; j++) {
// if row i and j share
// something in common
// then connect row i and j
if (shareCommon(arr[i], arr[j])) {
graph.get(i).add(j);
graph.get(j).add(i);
}
}
}
// queue fo BFS
Queue<Node> q = new ArrayDeque<>();
// visited array for bfs
boolean [] visited = new boolean [N];
// hashset to store rows
// having Y
HashSet<Integer> targetRows = new HashSet<>();
for ( int i = 0 ; i < N; i++) {
for ( int j = 0 ; j < arr[i].length; j++) {
if (arr[i][j] == Y) {
targetRows.add(i);
}
if (arr[i][j] == X && !visited[i]) {
q.add( new Node(i, 0 ));
visited[i] = true ;
}
}
}
// using bfs algorithm:
while (q.size() > 0 ) {
Node rm = q.remove();
// if the removed node is in
// the target row then return:
if (targetRows.contains(rm.rowNo)) {
if (rm.edgesTravelled == 0 ) {
System.out.println( 0 );
return ;
}
System.out.println(
rm.edgesTravelled - 1 );
return ;
}
// adding neighbouring nodes
for (Integer nbr : graph.get(rm.rowNo)) {
if (!visited[nbr]) {
int edgesTravelledBeforeNbr
= rm.edgesTravelled;
q.add( new Node(
nbr,
edgesTravelledBeforeNbr + 1 ));
visited[nbr] = true ;
}
}
}
// if bfs over
// => path not possible
System.out.println(- 1 );
}
// function to check connection b/w
// two rows
static boolean shareCommon( int [] i, int [] j)
{
// adding all elements
// of larger array to hashset
// then iterating other array
HashSet<Integer> row1 = new HashSet<>();
if (i.length > j.length) {
for ( int idx = 0 ; idx < i.length; idx++) {
row1.add(i[idx]);
}
for ( int idx = 0 ; idx < j.length; idx++) {
if (row1.contains(j[idx]))
return true ;
}
}
else {
for ( int idx = 0 ; idx < j.length; idx++) {
row1.add(j[idx]);
}
for ( int idx = 0 ; idx < i.length; idx++) {
if (row1.contains(i[idx]))
return true ;
}
}
return false ;
}
// class to represent node in queue
static class Node {
int rowNo;
int edgesTravelled;
Node( int r, int e)
{
this .rowNo = r;
this .edgesTravelled = e;
}
}
// driver code
public static void main(String[] args)
{
int [][] arr = { { 1 , 2 , 3 , 21 },
{ 1 , 11 , 12 , 25 },
{ 12 , 13 , 14 , 7 },
{ 3 , 5 , 6 , 7 },
{ 6 , 8 , 9 , 10 } };
int X = 1 ;
int Y = 9 ;
minRowsBetweenXY(arr, X, Y);
}
} |
# Python code to implement the approach # class to represent node in queue class Node:
def __init__( self , r, e):
self .rowNo = r
self .edgesTravelled = e
# function to check connection b/w two rows def shareCommon(i, j):
# adding all elements of larger array to hashset then
# iterating other array
row1 = set ()
if ( len (i) > len (j)):
for idx in range ( len (i)):
row1.add(i[idx])
for idx in range ( len (j)):
if (j[idx] in row1):
return True
else :
for idx in range ( len (j)):
row1.add(j[idx])
for idx in range ( len (i)):
if (i[idx] in row1):
return True
return False
def minRowsBetweenXY(arr, X, Y):
# No. of rows
N = len (arr)
if (X = = Y):
print ( 0 )
return
# constructing graph:
graph = [ 0 ] * N
for i in range (N):
graph[i] = []
for i in range (N):
for j in range (i + 1 , N):
# if row i and j share something in common then
# connect row i and j
if (shareCommon(arr[i], arr[j])):
graph[i].append(j)
graph[j].append(i)
# queue for BFS
q = []
# visited array for bfs
visited = [ 0 ] * N
for i in range (N):
visited[i] = False
# Set to store rows having Y
targetRows = set ()
for i in range (N):
for j in range ( len (arr[i])):
if (arr[i][j] = = Y):
targetRows.add(i)
if (arr[i][j] = = X and not visited[i]):
q.append(Node(i, 0 ))
# q.add(new Node(i, 0));
visited[i] = True
# using bfs algorithm:
while ( len (q) > 0 ):
rm = q[ 0 ]
q.pop( 0 )
# if the removed node is in the target row then
# return
if (rm.rowNo in targetRows):
if (rm.edgesTravelled = = 0 ):
print ( 0 )
return
print (rm.edgesTravelled - 1 )
return
# adding neighbouring nodes
for i in range ( len (graph[rm.rowNo])):
nbr = graph[rm.rowNo][i]
if ( not visited[nbr]):
edgesTravelledBeforeNbr = rm.edgesTravelled
q.append(Node(nbr, 1 + edgesTravelledBeforeNbr))
visited[nbr] = True
# if bfs over => path not possible
print ( - 1 )
# Driver code arr = [[ 1 , 2 , 3 , 21 ],
[ 1 , 11 , 12 , 25 ],
[ 12 , 13 , 14 , 7 ],
[ 3 , 5 , 6 , 7 ],
[ 6 , 8 , 9 , 10 ]
]
X = 1
Y = 9
minRowsBetweenXY(arr, X, Y) # This code is contributed by Saurabh Jaiswal |
// C# program to find minimum adjacent // rows between rows containing X and Y using System;
using System.Collections.Generic;
public class GFG {
// class to represent node in queue
public class Node {
public int rowNo;
public int edgesTravelled;
public Node( int r, int e)
{
this .rowNo = r;
this .edgesTravelled = e;
}
}
public static int [] GetRow( int [,] matrix, int row)
{
var rowLength = matrix.GetLength(1);
var rowVector = new int [rowLength];
for ( var i = 0; i < rowLength; i++)
rowVector[i] = matrix[row, i];
return rowVector;
}
static void minRowsBetweenXY( int [,] arr,
int X, int Y)
{
// No. of rows
int N = arr.GetLength(0);
if (X == Y) {
Console.WriteLine(0);
return ;
}
// constructing graph:
List<List< int > > graph
= new List<List< int > >();
for ( int i = 0; i < N; i++) {
graph.Add( new List< int >());
}
for ( int i = 0; i < N; i++) {
for ( int j = i + 1; j < N; j++) {
// if row i and j share
// something in common
// then connect row i and j
int [] t1 = GetRow(arr,i);
int [] t2 = GetRow(arr,j);
if (shareCommon(t1,t2)) {
graph[i].Add(j);
graph[j].Add(i);
}
}
}
// queue fo BFS
List<Node> q = new List<Node>();
// visited array for bfs
bool [] visited = new bool [N];
// hashset to store rows
// having Y
HashSet< int > targetRows = new HashSet< int >();
for ( int i = 0; i < N; i++) {
for ( int j = 0; j < arr.GetLength(1); j++) {
if (arr[i,j] == Y) {
targetRows.Add(i);
}
if (arr[i,j] == X && !visited[i]) {
q.Add( new Node(i, 0));
visited[i] = true ;
}
}
}
// using bfs algorithm:
while (q.Count > 0) {
Node rm = q[0];
q.RemoveAt(0);
// if the removed node is in
// the target row then return:
if (targetRows.Contains(rm.rowNo)) {
if (rm.edgesTravelled == 0) {
Console.WriteLine(0);
return ;
}
Console.WriteLine(
rm.edgesTravelled - 1);
return ;
}
// adding neighbouring nodes
foreach ( int nbr in graph[rm.rowNo]) {
if (!visited[nbr]) {
int edgesTravelledBeforeNbr
= rm.edgesTravelled;
q.Add( new Node(
nbr,
edgesTravelledBeforeNbr + 1));
visited[nbr] = true ;
}
}
}
// if bfs over
// => path not possible
Console.WriteLine(-1);
}
// function to check connection b/w
// two rows
static bool shareCommon( int [] i, int [] j)
{
// adding all elements
// of larger array to hashset
// then iterating other array
HashSet< int > row1 = new HashSet< int >();
if (i.Length > j.Length) {
for ( int idx = 0; idx < i.Length; idx++) {
row1.Add(i[idx]);
}
for ( int idx = 0; idx < j.Length; idx++) {
if (row1.Contains(j[idx]))
return true ;
}
}
else {
for ( int idx = 0; idx < j.Length; idx++) {
row1.Add(j[idx]);
}
for ( int idx = 0; idx < i.Length; idx++) {
if (row1.Contains(i[idx]))
return true ;
}
}
return false ;
}
// driver code
public static void Main(String[] args)
{
int [,] arr = { { 1, 2, 3, 21 },
{ 1, 11, 12, 25 },
{ 12, 13, 14, 7 },
{ 3, 5, 6, 7 },
{ 6, 8, 9, 10 } };
int X = 1;
int Y = 9;
minRowsBetweenXY(arr, X, Y);
}
} // This code is contributed by shikhasingrajput |
<script> // Javascript code to implement the approach
// class to represent node in queue
class Node {
constructor(r, e)
{
this .rowNo = r;
this .edgesTravelled = e;
}
}
// function to check connection b/w two rows
function shareCommon(i, j)
{
// adding all elements of larger array to hashset then
// iterating other array
var row1 = new Set()
if (i.length > j.length) {
for (let idx = 0; idx < i.length; idx++) {
row1.add(i[idx])
}
for (let idx = 0 ; idx < j.length ; idx++) {
if (row1.has(j[idx])){
return true
}
}
}
else {
for (let idx = 0; idx < j.length; idx++) {
row1.add(j[idx]);
}
for (let idx = 0; idx < i.length; idx++) {
if (row1.has(i[idx])){
return true
}
}
}
return false ;
}
function minRowsBetweenXY(arr, X, Y)
{
// No. of rows
let N = arr.length;
if (X == Y) {
console.log(0)
return ;
}
// constructing graph:
var graph = Array(N)
for (let i = 0 ; i < N ; i++){
graph[i] = Array()
}
for (let i = 0; i < N; i++) {
for (let j = i + 1; j < N; j++) {
// if row i and j share something in common then
// connect row i and j
if (shareCommon(arr[i], arr[j])) {
graph[i].push(j);
graph[j].push(i);
}
}
}
// queue for BFS
var q = Array()
// visited array for bfs
var visited = Array(N);
for (let i = 0 ; i < N ; i++){
visited[i] = false
}
// Set to store rows having Y
var targetRows = new Set()
for (let i = 0; i < N; i++) {
for (let j = 0; j < arr[i].length; j++) {
if (arr[i][j] == Y) {
targetRows.add(i)
}
if (arr[i][j] == X && !visited[i]) {
q.push( new Node(i, 0))
// q.add(new Node(i, 0));
visited[i] = true
}
}
}
// using bfs algorithm:
while (q.length > 0) {
var rm = q[0]
q.shift()
// if the removed node is in the target row then
// return
if (targetRows.has(rm.rowNo)) {
if (rm.edgesTravelled == 0) {
console.log(0)
return ;
}
console.log(rm.edgesTravelled - 1)
return ;
}
// adding neighbouring nodes
for (let i = 0 ; i < graph[rm.rowNo].length ; i++){
var nbr = graph[rm.rowNo][i]
if (!visited[nbr]) {
let edgesTravelledBeforeNbr = rm.edgesTravelled;
q.push( new Node(nbr, 1 + edgesTravelledBeforeNbr));
visited[nbr] = true ;
}
}
}
// if bfs over => path not possible
console.log(-1)
}
// Driver code
var arr = [ [ 1, 2, 3, 21 ],
[ 1, 11, 12, 25 ],
[ 12, 13, 14, 7 ],
[ 3, 5, 6, 7 ],
[ 6, 8, 9, 10 ]
];
var X = 1;
var Y = 9;
minRowsBetweenXY(arr, X, Y);
// This code is contributed by subhamgoyal2014.
</script> |
1
Time Complexity: O(N2 + N * M)
Auxiliary Space: O(N2 + M)