You are given a 2D integer array mat
where each row is sorted in strictly increasing order. Your task is to find the smallest common element present in all rows of mat
. If there is no such common element, return -1
.
mat
is sorted in strictly increasing order.-1
.To solve this problem, we need to find an integer that appears in every row of the matrix. The brute-force approach would be to check every element in the matrix against all rows, but this is inefficient, especially for large matrices.
Instead, we can take advantage of the fact that each row is sorted in strictly increasing order. This means we can use more efficient searching techniques, such as using pointers or hash maps to keep track of element occurrences.
The initial idea is: for each element in the first row, check if it exists in all other rows. If we find such an element, it is a candidate for the answer. We want the smallest such element, so we process the first row from left to right.
However, this can still be improved. By using hash maps or pointers, and leveraging the sorted nature of the rows, we can avoid unnecessary checks and make the process much faster.
Let's break down the optimized approach step by step:
Let's use the following example:
mat = [ [1, 2, 3, 4, 5], [2, 4, 5, 8, 10], [4, 5, 8, 9, 10] ]
[1, 2, 4]
[4, 4, 4]
(indices [3,1,0]).If there is no such common element, the pointers will eventually reach the end of a row and we return -1.
Brute-force approach:
By leveraging the sorted property of each row, we can efficiently find the smallest common element using pointers, similar to merging sorted lists. This approach avoids unnecessary work and ensures we find the answer as quickly as possible, or determine that no common element exists. The key insight is to always move forward the pointers with the smallest current value, and check for equality across all rows at each step.
class Solution:
def smallestCommonElement(self, mat):
m, n = len(mat), len(mat[0])
pointers = [0] * m
while True:
current = [mat[i][pointers[i]] for i in range(m)]
max_val = max(current)
# If all values are equal, found the common element
if all(val == max_val for val in current):
return max_val
# Advance pointers which are less than max_val
for i in range(m):
while pointers[i] < n and mat[i][pointers[i]] < max_val:
pointers[i] += 1
if pointers[i] == n:
return -1
class Solution {
public:
int smallestCommonElement(vector<vector<int>>& mat) {
int m = mat.size(), n = mat[0].size();
vector<int> pointers(m, 0);
while (true) {
int max_val = mat[0][pointers[0]];
for (int i = 1; i < m; ++i)
max_val = max(max_val, mat[i][pointers[i]]);
bool all_equal = true;
for (int i = 0; i < m; ++i)
if (mat[i][pointers[i]] != max_val)
all_equal = false;
if (all_equal)
return max_val;
for (int i = 0; i < m; ++i) {
while (pointers[i] < n && mat[i][pointers[i]] < max_val)
pointers[i]++;
if (pointers[i] == n)
return -1;
}
}
}
};
class Solution {
public int smallestCommonElement(int[][] mat) {
int m = mat.length, n = mat[0].length;
int[] pointers = new int[m];
while (true) {
int maxVal = mat[0][pointers[0]];
for (int i = 1; i < m; i++)
maxVal = Math.max(maxVal, mat[i][pointers[i]]);
boolean allEqual = true;
for (int i = 0; i < m; i++) {
if (mat[i][pointers[i]] != maxVal)
allEqual = false;
}
if (allEqual)
return maxVal;
for (int i = 0; i < m; i++) {
while (pointers[i] < n && mat[i][pointers[i]] < maxVal)
pointers[i]++;
if (pointers[i] == n)
return -1;
}
}
}
}
var smallestCommonElement = function(mat) {
let m = mat.length, n = mat[0].length;
let pointers = new Array(m).fill(0);
while (true) {
let current = pointers.map((ptr, i) => mat[i][ptr]);
let maxVal = Math.max(...current);
if (current.every(val => val === maxVal))
return maxVal;
for (let i = 0; i < m; ++i) {
while (pointers[i] < n && mat[i][pointers[i]] < maxVal)
pointers[i]++;
if (pointers[i] === n)
return -1;
}
}
};