Given an m x n
matrix of distinct numbers, return all lucky numbers in the matrix in any order.
A lucky number is an element of the matrix such that it is the minimum element in its row and maximum in its column.
Example 1:
Input: matrix = [[3,7,8],[9,11,13],[15,16,17]] Output: [15] Explanation: 15 is the only lucky number since it is the minimum in its row and the maximum in its column.
Example 2:
Input: matrix = [[1,10,4,2],[9,3,8,7],[15,16,17,12]] Output: [12] Explanation: 12 is the only lucky number since it is the minimum in its row and the maximum in its column.
Example 3:
Input: matrix = [[7,8],[1,2]] Output: [7] Explanation: 7 is the only lucky number since it is the minimum in its row and the maximum in its column.
Constraints:
m == mat.length
n == mat[i].length
1 <= n, m <= 50
1 <= matrix[i][j] <= 105
.This problem asks to find all "lucky numbers" within a given matrix. A lucky number is defined as an element that's both the minimum value in its row and the maximum value in its column.
The most efficient approach is a two-pass algorithm:
1. Finding Row Minimums and Column Maximums:
zip(*matrix)
in Python (transposing the matrix) or similar techniques in other languages.2. Identifying Lucky Numbers:
Time Complexity: O(m*n), where 'm' is the number of rows and 'n' is the number of columns. We iterate through the matrix twice.
Space Complexity: O(m+n). We use arrays (or sets in Python's case) of size 'm' and 'n' to store row minimums and column maximums respectively.
Code Implementations:
Python3:
class Solution:
def luckyNumbers(self, matrix: List[List[int]]) -> List[int]:
rows = {min(row) for row in matrix} #Set for efficient lookup
cols = {max(col) for col in zip(*matrix)} #Zip transposes the matrix
return list(rows & cols) #Intersection of sets finds lucky numbers
Java:
import java.util.*;
class Solution {
public List<Integer> luckyNumbers (int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
int[] rowMin = new int[m];
int[] colMax = new int[n];
Arrays.fill(rowMin, Integer.MAX_VALUE); //Initialize with maximum possible int value
for(int i=0; i<m; ++i){
for(int j=0; j<n; ++j){
rowMin[i] = Math.min(rowMin[i], matrix[i][j]);
colMax[j] = Math.max(colMax[j], matrix[i][j]);
}
}
List<Integer> result = new ArrayList<>();
for(int i=0; i<m; ++i){
for(int j=0; j<n; ++j){
if(matrix[i][j] == rowMin[i] && matrix[i][j] == colMax[j]){
result.add(matrix[i][j]);
}
}
}
return result;
}
}
C++:
#include <vector>
#include <algorithm>
using namespace std;
class Solution {
public:
vector<int> luckyNumbers(vector<vector<int>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();
vector<int> rowMin(m, INT_MAX); //Initialize with maximum possible int value
vector<int> colMax(n, INT_MIN); //Initialize with minimum possible int value
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
rowMin[i] = min(rowMin[i], matrix[i][j]);
colMax[j] = max(colMax[j], matrix[i][j]);
}
}
vector<int> result;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (matrix[i][j] == rowMin[i] && matrix[i][j] == colMax[j]) {
result.push_back(matrix[i][j]);
}
}
}
return result;
}
};
Go:
func luckyNumbers(matrix [][]int) []int {
m, n := len(matrix), len(matrix[0])
rowMin := make([]int, m)
colMax := make([]int, n)
for i := 0; i < m; i++ {
rowMin[i] = math.MaxInt32
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
rowMin[i] = min(rowMin[i], matrix[i][j])
colMax[j] = max(colMax[j], matrix[i][j])
}
}
var result []int
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if matrix[i][j] == rowMin[i] && matrix[i][j] == colMax[j] {
result = append(result, matrix[i][j])
}
}
}
return result
}
The other languages (TypeScript, JavaScript, Rust) would follow a similar structure, adapting the array/list handling and min/max functions to their respective syntax. The core algorithm remains consistent.