Given a matrix where every row is sorted in increasing order. Write a function that finds and returns a common element in all rows. If there is no common element, then returns -1.
Example:
Input: mat[4][5] = { {1, 2, 3, 4, 5},
{2, 4, 5, 8, 10},
{3, 5, 7, 9, 11},
{1, 3, 5, 7, 9},
};
Output: 5
A O(m*n*n) simple solution is to take every element of first row and search it in all other rows, till we find a common element. Time complexity of this solution is O(m*n*n) where m is number of rows and n is number of columns in given matrix. This can be improved to O(m*n*Logn) if we use Binary Search instead of linear search.
We can solve this problem in O(mn) time using the approach similar to merge of Merge Sort. The idea is to start from the last column of every row. If elements at all last columns are same, then we found the common element. Otherwise we find the minimum of all last columns. Once we find a minimum element, we know that all other elements in last columns cannot be a common element, so we reduce last column index for all rows except for the row which has minimum value. We keep repeating these steps till either all elements at current last column don’t become same, or a last column index reaches 0.
Below is the implementation of above idea.
C++
#include <bits/stdc++.h>
using namespace std;
#define M 4
#define N 5
int findCommon( int mat[M][N])
{
int column[M];
int min_row;
int i;
for (i = 0; i < M; i++)
column[i] = N - 1;
min_row = 0;
while (column[min_row] >= 0) {
for (i = 0; i < M; i++) {
if (mat[i][column[i]] < mat[min_row][column[min_row]])
min_row = i;
}
int eq_count = 0;
for (i = 0; i < M; i++) {
if (mat[i][column[i]] > mat[min_row][column[min_row]]) {
if (column[i] == 0)
return -1;
column[i] -= 1;
}
else
eq_count++;
}
if (eq_count == M)
return mat[min_row][column[min_row]];
}
return -1;
}
int main()
{
int mat[M][N] = {
{ 1, 2, 3, 4, 5 },
{ 2, 4, 5, 8, 10 },
{ 3, 5, 7, 9, 11 },
{ 1, 3, 5, 7, 9 },
};
int result = findCommon(mat);
if (result == -1)
cout << "No common element" ;
else
cout << "Common element is " << result;
return 0;
}
|
C
#include <stdio.h>
#define M 4
#define N 5
int findCommon( int mat[M][N])
{
int column[M];
int min_row;
int i;
for (i = 0; i < M; i++)
column[i] = N - 1;
min_row = 0;
while (column[min_row] >= 0) {
for (i = 0; i < M; i++) {
if (mat[i][column[i]] < mat[min_row][column[min_row]])
min_row = i;
}
int eq_count = 0;
for (i = 0; i < M; i++) {
if (mat[i][column[i]] > mat[min_row][column[min_row]]) {
if (column[i] == 0)
return -1;
column[i] -= 1;
}
else
eq_count++;
}
if (eq_count == M)
return mat[min_row][column[min_row]];
}
return -1;
}
int main()
{
int mat[M][N] = {
{ 1, 2, 3, 4, 5 },
{ 2, 4, 5, 8, 10 },
{ 3, 5, 7, 9, 11 },
{ 1, 3, 5, 7, 9 },
};
int result = findCommon(mat);
if (result == -1)
printf ( "No common element" );
else
printf ( "Common element is %d" , result);
return 0;
}
|
Java
class GFG {
static final int M = 4 ;
static final int N = 5 ;
static int findCommon( int mat[][])
{
int column[] = new int [M];
int min_row;
int i;
for (i = 0 ; i < M; i++)
column[i] = N - 1 ;
min_row = 0 ;
while (column[min_row] >= 0 ) {
for (i = 0 ; i < M; i++) {
if (mat[i][column[i]] < mat[min_row][column[min_row]])
min_row = i;
}
int eq_count = 0 ;
for (i = 0 ; i < M; i++) {
if (mat[i][column[i]] > mat[min_row][column[min_row]]) {
if (column[i] == 0 )
return - 1 ;
column[i] -= 1 ;
}
else
eq_count++;
}
if (eq_count == M)
return mat[min_row][column[min_row]];
}
return - 1 ;
}
public static void main(String[] args)
{
int mat[][] = { { 1 , 2 , 3 , 4 , 5 },
{ 2 , 4 , 5 , 8 , 10 },
{ 3 , 5 , 7 , 9 , 11 },
{ 1 , 3 , 5 , 7 , 9 } };
int result = findCommon(mat);
if (result == - 1 )
System.out.print( "No common element" );
else
System.out.print( "Common element is " + result);
}
}
|
Python 3
M = 4
N = 5
def findCommon(mat):
column = [N - 1 ] * M
min_row = 0
while (column[min_row] > = 0 ):
for i in range (M):
if (mat[i][column[i]] <
mat[min_row][column[min_row]]):
min_row = i
eq_count = 0
for i in range (M):
if (mat[i][column[i]] >
mat[min_row][column[min_row]]):
if (column[i] = = 0 ):
return - 1
column[i] - = 1
else :
eq_count + = 1
if (eq_count = = M):
return mat[min_row][column[min_row]]
return - 1
if __name__ = = "__main__" :
mat = [[ 1 , 2 , 3 , 4 , 5 ],
[ 2 , 4 , 5 , 8 , 10 ],
[ 3 , 5 , 7 , 9 , 11 ],
[ 1 , 3 , 5 , 7 , 9 ]]
result = findCommon(mat)
if (result = = - 1 ):
print ( "No common element" )
else :
print ( "Common element is" , result)
|
C#
using System;
class GFG {
static int M = 4;
static int N = 5;
static int findCommon( int [, ] mat)
{
int [] column = new int [M];
int min_row;
int i;
for (i = 0; i < M; i++)
column[i] = N - 1;
min_row = 0;
while (column[min_row] >= 0) {
for (i = 0; i < M; i++) {
if (mat[i, column[i]] < mat[min_row, column[min_row]])
min_row = i;
}
int eq_count = 0;
for (i = 0; i < M; i++) {
if (mat[i, column[i]] > mat[min_row, column[min_row]]) {
if (column[i] == 0)
return -1;
column[i] -= 1;
}
else
eq_count++;
}
if (eq_count == M)
return mat[min_row,
column[min_row]];
}
return -1;
}
public static void Main()
{
int [, ] mat = { { 1, 2, 3, 4, 5 },
{ 2, 4, 5, 8, 10 },
{ 3, 5, 7, 9, 11 },
{ 1, 3, 5, 7, 9 } };
int result = findCommon(mat);
if (result == -1)
Console.Write( "No common element" );
else
Console.Write( "Common element is "
+ result);
}
}
|
Javascript
<script>
let M = 4;
let N = 5;
function findCommon(mat)
{
let column= new Array(M);
let min_row;
let i;
for (i = 0; i < M; i++)
column[i] = N - 1;
min_row = 0;
while (column[min_row] >= 0) {
for (i = 0; i < M; i++) {
if (mat[i][column[i]] < mat[min_row][column[min_row]])
min_row = i;
}
let eq_count = 0;
for (i = 0; i < M; i++) {
if (mat[i][column[i]] > mat[min_row][column[min_row]]) {
if (column[i] == 0)
return -1;
column[i] -= 1;
}
else
eq_count++;
}
if (eq_count == M)
return mat[min_row][column[min_row]];
}
return -1;
}
let mat = [[1, 2, 3, 4, 5],
[2, 4, 5, 8, 10],
[3, 5, 7, 9, 11],
[1, 3, 5, 7, 9]];
let result = findCommon(mat)
if (result == -1)
{
document.write( "No common element" );
}
else
{
document.write( "Common element is " , result);
}
</script>
|
Output:
Common element is 5
Time complexity: O(M x N).
Auxiliary Space: O(M)
Explanation for working of above code
Let us understand working of above code for following example.
Initially entries in last column array are N-1, i.e., {4, 4, 4, 4}
{1, 2, 3, 4, 5},
{2, 4, 5, 8, 10},
{3, 5, 7, 9, 11},
{1, 3, 5, 7, 9},
The value of min_row is 0, so values of last column index for rows with value greater than 5 is reduced by one. So column[] becomes {4, 3, 3, 3}.
{1, 2, 3, 4, 5},
{2, 4, 5, 8, 10},
{3, 5, 7, 9, 11},
{1, 3, 5, 7, 9},
The value of min_row remains 0 and value of last column index for rows with value greater than 5 is reduced by one. So column[] becomes {4, 2, 2, 2}.
{1, 2, 3, 4, 5},
{2, 4, 5, 8, 10},
{3, 5, 7, 9, 11},
{1, 3, 5, 7, 9},
The value of min_row remains 0 and value of last column index for rows with value greater than 5 is reduced by one. So column[] becomes {4, 2, 1, 2}.
{1, 2, 3, 4, 5},
{2, 4, 5, 8, 10},
{3, 5, 7, 9, 11},
{1, 3, 5, 7, 9},
Now all values in current last columns of all rows is same, so 5 is returned.
A Hashing Based Solution
We can also use hashing. This solution works even if the rows are not sorted. It can be used to print all common elements.
Step1: Create a Hash Table with all key as distinct elements
of row1. Value for all these will be 0.
Step2:
For i = 1 to M-1
For j = 0 to N-1
If (mat[i][j] is already present in Hash Table)
If (And this is not a repetition in current row.
This can be checked by comparing HashTable value with
row number)
Update the value of this key in HashTable with current
row number
Step3: Iterate over HashTable and print all those keys for
which value = M
C++
#include <bits/stdc++.h>
using namespace std;
#define M 4
#define N 5
int findCommon( int grid[M][N])
{
unordered_map< int , int > cnt;
int i, j;
for (i = 0; i < M; i++) {
cnt[grid[i][0]]++;
for (j = 1; j < N; j++) {
if (grid[i][j] != grid[i][j - 1])
cnt[grid[i][j]]++;
}
}
for ( auto ele : cnt) {
if (ele.second == M)
return ele.first;
}
return -1;
}
int main()
{
int mat[M][N] = {
{ 1, 2, 3, 4, 5 },
{ 2, 4, 5, 8, 10 },
{ 3, 5, 7, 9, 11 },
{ 1, 3, 5, 7, 9 },
};
int result = findCommon(mat);
if (result == -1)
cout << "No common element" ;
else
cout << "Common element is " << result;
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int M = 4 ;
static int N = 5 ;
static int findCommon( int mat[][])
{
HashMap<Integer,
Integer> cnt = new HashMap<Integer,
Integer>();
int i, j;
for (i = 0 ; i < M; i++)
{
if (cnt.containsKey(mat[i][ 0 ]))
{
cnt.put(mat[i][ 0 ],
cnt.get(mat[i][ 0 ]) + 1 );
}
else
{
cnt.put(mat[i][ 0 ], 1 );
}
for (j = 1 ; j < N; j++)
{
if (mat[i][j] != mat[i][j - 1 ])
if (cnt.containsKey(mat[i][j]))
{
cnt.put(mat[i][j],
cnt.get(mat[i][j]) + 1 );
}
else
{
cnt.put(mat[i][j], 1 );
}
}
}
for (Map.Entry<Integer,
Integer> ele : cnt.entrySet())
{
if (ele.getValue() == M)
return ele.getKey();
}
return - 1 ;
}
public static void main(String[] args)
{
int mat[][] = {{ 1 , 2 , 3 , 4 , 5 },
{ 2 , 4 , 5 , 8 , 10 },
{ 3 , 5 , 7 , 9 , 11 },
{ 1 , 3 , 5 , 7 , 9 }};
int result = findCommon(mat);
if (result == - 1 )
System.out.println( "No common element" );
else
System.out.println( "Common element is " + result);
}
}
|
Python
from collections import defaultdict
M = 4
N = 5
def findCommon(grid):
global M
global N
cnt = dict ()
cnt = defaultdict( lambda : 0 , cnt)
i = 0
j = 0
while (i < M ):
cnt[grid[i][ 0 ]] = cnt[grid[i][ 0 ]] + 1
j = 1
while (j < N ) :
if (grid[i][j] ! = grid[i][j - 1 ]):
cnt[grid[i][j]] = cnt[grid[i][j]] + 1
j = j + 1
i = i + 1
for ele in cnt:
if (cnt[ele] = = M):
return ele
return - 1
mat = [[ 1 , 2 , 3 , 4 , 5 ],
[ 2 , 4 , 5 , 8 , 10 ],
[ 3 , 5 , 7 , 9 , 11 ],
[ 1 , 3 , 5 , 7 , 9 ],]
result = findCommon(mat)
if (result = = - 1 ):
print ( "No common element" )
else :
print ( "Common element is " , result)
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int M = 4;
static int N = 5;
static int findCommon( int [,]grid)
{
Dictionary< int ,
int > cnt = new Dictionary< int ,
int >();
int i, j;
for (i = 0; i < M; i++)
{
if (cnt.ContainsKey(grid[i, 0]))
{
cnt[grid[i, 0]]= cnt[grid[i, 0]] + 1;
}
else
{
cnt.Add(grid[i, 0], 1);
}
for (j = 1; j < N; j++)
{
if (grid[i, j] != grid[i, j - 1])
if (cnt.ContainsKey(mat[i, j]))
{
cnt[grid[i, j]]= cnt[grid[i, j]] + 1;
}
else
{
cnt.Add(grid[i, j], 1);
}
}
}
foreach (KeyValuePair< int , int > ele in cnt)
{
if (ele.Value == M)
return ele.Key;
}
return -1;
}
public static void Main(String[] args)
{
int [,]mat = {{ 1, 2, 3, 4, 5 },
{ 2, 4, 5, 8, 10 },
{ 3, 5, 7, 9, 11 },
{ 1, 3, 5, 7, 9 }};
int result = findCommon(mat);
if (result == -1)
Console.WriteLine( "No common element" );
else
Console.WriteLine( "Common element is " + result);
}
}
|
Javascript
<script>
let M = 4;
let N = 5;
function findCommon(mat)
{
let cnt = new Map();
let i, j;
for (i = 0; i < M; i++)
{
if (cnt.has(mat[i][0]))
{
cnt.set(mat[i][0],cnt.get(mat[i][0])+1);
}
else
{
cnt.set(mat[i][0],1);
}
for (j = 1; j < N; j++)
{
if (mat[i][j] != mat[i][j - 1])
{
if (cnt.has(mat[i][j]))
{
cnt.set(mat[i][j], cnt.get(mat[i][j]) + 1);
}
else
{
cnt.set(mat[i][j], 1);
}
}
}
}
for ( let [key, value] of cnt.entries())
{
if (value == M)
return key;
}
return -1;
}
let mat = [[1, 2, 3, 4, 5 ],
[2, 4, 5, 8, 10],
[3, 5, 7, 9, 11],
[1, 3, 5, 7, 9 ],]
let result = findCommon(mat);
if (result == -1)
document.write( "No common element" );
else
document.write( "Common element is " + result);
</script>
|
Output:
Common element is 5
Time complexity: O(n*m) under the assumption that search and insert in HashTable take O(1) time
Auxiliary Space: O(n) due to unordered_map.
Thanks to Nishant for suggesting this solution in a comment below.
Exercise: Given n sorted arrays of size m each, find all common elements in all arrays in O(mn) time.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...