Open In App

Minimum count of rows between rows containing X and Y respectively

Improve
Improve
Like Article
Like
Save
Share
Report

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.
  • 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++




// 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




// 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);
    }
}


Python3




# 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#




// 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


Javascript




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


 
 

Output: 

1

 

 

Time Complexity: O(N2 + N * M)
Auxiliary Space: O(N2 + M) 

 



Last Updated : 27 Jan, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads