分别包含 X 和 Y 的行之间的最小行数
给定一个大小为NxM的Grid和两个整数X和Y ,任务是计算包含X的行和包含Y的行之间的最小行数,使得它们之间的相邻行至少有一个元素共同点。网格中允许多次出现一个数字。换句话说,如果两行至少有一个共同的元素,则称它们是相邻的。
例子:
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.
方法:给定的问题可以通过使用BFS 算法的未加权图中的最短路径来解决。
- 创建一个未加权图,其中每个节点代表一行。
- 如果该图的两个节点之间共享至少 1 个公共数字,则它们是连接的。
- 从i = 0 到 N运行外部 for 循环,其中N是行数。
- 运行从j = i + 1 到 N的内部循环。
- 如果两行有共同点,则连接“i”行和“j”行。
- 从i = 0 到 N运行外部 for 循环,其中N是行数。
- 现在问题简化为找到从具有 X 的节点到具有 Y 的节点的最短路径。
- 再次运行另一个嵌套循环并将具有 X 的行存储在队列中以用于BFS。
- 此外,存储所有具有 Y 的行,它将用于检测节点是否达到目标编号。
- 如果图的BFS 遍历中的当前节点有 Y,则返回经过的边数 - 1。
- 如果 BFS 结束,则返回-1 ,两行之间没有可能的相邻行组合。
下面是上述方法的实现:
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 > graph
= new ArrayList >();
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 q = new ArrayDeque<>();
// visited array for bfs
boolean[] visited = new boolean[N];
// hashset to store rows
// having Y
HashSet 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 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);
}
}
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 > graph
= new List >();
for (int i = 0; i < N; i++) {
graph.Add(new List());
}
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 q = new List();
// visited array for bfs
bool[] visited = new bool[N];
// hashset to store rows
// having Y
HashSet targetRows = new HashSet();
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 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;
}
// 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
1
时间复杂度: O(N 2 + N * M)
辅助空间: O(N 2 + M)