Find Smallest Common Element in All Rows

Updated on 27 May, 2025
Find Smallest Common Element in All Rows header image

Problem Statement

In this task, we are provided with a matrix mat of dimensions m x n, where each row of the matrix is sorted in a strictly increasing order. The goal is to find the smallest element which is common across all the rows of the matrix. If no such common element exists, the function should return -1. This type of problem tests both your understanding of matrix manipulation and the ability to apply search algorithms due to the sorted nature of the rows.

Examples

Example 1

Input:

mat = [[1,2,3,4,5],[2,4,5,8,10],[3,5,7,9,11],[1,3,5,7,9]]

Output:

5

Example 2

Input:

mat = [[1,2,3],[2,3,4],[2,3,5]]

Output:

2

Constraints

  • m == mat.length
  • n == mat[i].length
  • 1 <= m, n <= 500
  • 1 <= mat[i][j] <= 104
  • mat[i] is sorted in strictly increasing order.

Approach and Intuition

  1. Use of Frequency Counting: A straightforward way to approach the smallest common element problem is to utilize a frequency counting mechanism. Since the matrix rows are sorted, we can efficiently count the occurrence of each element.

    • Create a frequency map to count the occurrences of each element across all rows.
    • Traverse each row and for each element, increase its count in the map.
    • After processing all rows, identify the smallest element that has a frequency equal to the number of rows (m).
  2. Optimization with Early Stopping: Given the sorted nature of each row, once we encounter an element in the first row, there's potential to stop further comparisons in other rows as soon as the number of remaining elements in any row is less than the count of the already processed rows. This can significantly reduce the number of comparisons in scenarios with large matrices.

    • Begin by traversing the first row and checking if each of its elements appears in every other row.
    • If an element from the first row does not exist in any subsequent row, skip to the next element.
    • If an element exists in every row, track this as a potential answer. If multiple common elements exist, choose the smallest.
  3. Binary Search for Efficiency: To leverage the sorted order of rows, implement a binary search for each element of the first row in all other rows. This improves the average time complexity in comparison to a linear search, provided the matrix has a considerable number of columns.

    • For each element in the first row, use binary search in the subsequent rows.
    • If the element is found in all rows, consider it as a potential smallest common element.
    • The first confirmed common element will be the smallest due to the sorted property of rows.

This problem allows the implementation of different algorithms based on the matrix size and expected time complexity. In scenarios with higher constraints, the operations must be efficiently managed to fit the operations within permissible limits.

Solutions

  • C++
  • Java
cpp
int linearSearchEnhanced(vector<int> &sequence, int index, int target, int step = 1) {
    int length = sequence.size();
    while (index < length && sequence[index] < target) {
        step <<= 1;
        if (sequence[min(index + step, length - 1)] >= target) {
            step = 1;
        }
        index += step;
    }
    return index;
}

int smallestCommon(vector<vector<int>>& matrix) {
    int rows = matrix.size(), cols = matrix[0].size();
    int maxElement = 0, matchCnt = 0;
    vector<int> indices(rows);
    while (true) {
        for (int i = 0; i < rows; ++i) {
            indices[i] = linearSearchEnhanced(matrix[i], indices[i], maxElement);
            if (indices[i] >= cols) {
                return -1;
            }
            if (maxElement != matrix[i][indices[i]]) {
                matchCnt = 1;
                maxElement = matrix[i][indices[i]];
            } else if (++matchCnt == rows) {
                return maxElement;
            }
        }
    }
    return -1;
}

The provided C++ code defines a solution to find the smallest common element in all rows of a matrix. The solution utilizes two primary functions: linearSearchEnhanced and smallestCommon.

  • linearSearchEnhanced function takes a vector sequence and an index, along with a target element and a step parameter initialized to 1.

    • This function uses a modified linear search algorithm that increases the step size exponentially (by doubling it) until a candidate position that is greater than or equal to the target is found or the end of the vector is reached.
    • If such position is found, it resets the step increment to 1, and the search continues in smaller increments.
    • The index of the position where the target could be placed according to the sequence's order is returned.
  • smallestCommon function accepts a matrix and aims to find the smallest element present in all rows using the above search technique.

    • Initializes variables for tracking the number of rows and columns, and maintains a list of indices to track the current search start positions for each row.
    • Iterates through all rows, updating each row's index using linearSearchEnhanced, which either jumps ahead based on current maximum element or proceeds linearly.
    • If during any update a target element from one row matches the maximum explored element and is found in all the rows, it's returned immediately as the result.
    • If an index exceeds the length of row during search, indicating no common elements left, it returns -1.

Take note of these points:

  • The solution uses an efficient approach to reduce time complexity by augmenting linear search with an exponential step growth when elements are sorted.
  • The use of a vector to manage search indices for each row makes it possible to efficiently track and compare across different rows.
  • Once a candidate element is found in all rows, the function exits immediately, which optimizes performance, especially in cases where a common element is located early in the matrix.
java
private int binaryStepSearch(int[] sequence, int start, int target) {
    int length = sequence.length, step = 1;
    while (start < length && sequence[start] < target) {
        step <<= 1;
        if (sequence[Math.min(start + step, length - 1)] >= target) {
            step = 1;
        }
        start += step;
    }
    return start;
}    
public int findLowestCommonElement(int[][] matrix) {
    int rows = matrix.length, cols = matrix[0].length;
    int indices[] = new int[rows], maxElement = 0, matchCount = 0;
    while (true) {
        for (int i = 0; i < rows; ++i) {
            indices[i] = binaryStepSearch(matrix[i], indices[i], maxElement);
            if (indices[i] >= cols) {
                return -1;
            }
            if (matrix[i][indices[i]] != maxElement) {
                matchCount = 1;
                maxElement = matrix[i][indices[i]];
            } else if (++matchCount == rows) {
                return maxElement;
            }
        }
    }
}

The Java solution provided tackles the problem of finding the smallest common element in all rows of a given 2D matrix. The process leverages a binary-search style approach to efficiently find this element. Here’s a straightforward breakdown of the solution’s execution:

  • Define a binaryStepSearch method to use binary search for efficiently finding the index at which an element (or larger) first appears in the array from a specified start position.

    • Initialize variables for step increments and iteratively double the step size to skip through elements quickly.
    • Adjust the step back to 1 whenever the next element equals or exceeds the target, to narrow down the search precisely.
  • In the findLowestCommonElement method:

    • Initialize necessary variables including an array to keep track of indices across different rows and variables to store the current maximal element being inspected and a count of matches for this element across rows.
    • Use a while loop to continually traverse each row from its respective index to look for the maximum element that matches in all rows.
      • If an end of a row is reached (index surpasses column length), conclude that there is no common element by returning –1.
      • For each row, use binaryStepSearch to update the row’s index to where the current maximum or a higher element is found.
      • If a new element is detected (i.e., the current element from the row doesn’t match maxElement), reset the match count, and update maxElement.
      • If all rows end up having the same maxElement based on the updated indices, and the match count equals the number of rows, return this maxElement as it's the smallest common element found.

This efficient approach minimizes the number of comparisons needed by skipping through unnecessary elements within each row, significantly speeding up the process in larger matrices.

Comments

No comments yet.