LeetCode 1380. 矩阵中的幸运数

给你一个 m * n 的矩阵,矩阵中的数字 各不相同 。请你按 任意 顺序返回矩阵中的所有幸运数。

幸运数 是指矩阵中满足同时下列两个条件的元素:

在同一行的所有元素中最小
在同一列的所有元素中最大

示例 1:

输入:matrix = [[3,7,8],[9,11,13],[15,16,17]]
输出:[15]
解释:15 是唯一的幸运数,因为它是其所在行中的最小值,也是所在列中的最大值。

m == mat.length
n == mat[i].length
1 <= n, m <= 50
1 <= matrix[i][j] <= 10^5
矩阵中的所有元素都是不同的

解法一:直接模拟:

class Solution {
public:
    vector<int> luckyNumbers(vector<vector<int>>& matrix) {
        int rowNum = matrix.size();
        int colNum = matrix[0].size();
        vector<int> ans;
        for (int row = 0; row < rowNum; ++row) {
            for (int col = 0; col < colNum; ++col) {
                int i = 0;
                for (; i < rowNum; ++i) {
                    if (matrix[i][col] > matrix[row][col]) {
                        break;
                    }
                }
                if (i != rowNum) {
                    continue;
                }

                i = 0;
                for (; i < colNum; ++i) {
                    if (matrix[row][i] < matrix[row][col]) {
                        break;
                    }
                }
                if (i != colNum) {
                    continue;
                } 

                ans.push_back(matrix[row][col]);
            }
        }

        return ans;
    }
};

如果矩阵有n行m列,此算法时间复杂度为O(mn(m+n)),空间复杂度为O(1)。

解法二:先找出每一行的最小值和每一列的最大值,然后遍历矩阵,看当前遍历到的值是否是幸运数:

class Solution {
public:
    vector<int> luckyNumbers(vector<vector<int>>& matrix) {
        int rowNum = matrix.size();
        int colNum = matrix[0].size();
        vector<int> maxCol(colNum), minRow(rowNum, INT_MAX);
        for (int row = 0; row < rowNum; ++row) {
            for (int col = 0; col < colNum; ++col) {
                maxCol[col] = max(matrix[row][col], maxCol[col]);
                minRow[row] = min(matrix[row][col], minRow[row]);
            }
        }

        vector<int> ans;
        for (int row = 0; row < rowNum; ++row) {
            for (int col = 0; col < colNum; ++col) {
                if (matrix[row][col] == maxCol[col] && matrix[row][col] == minRow[row]) {
                    ans.push_back(matrix[row][col]);
                }
            }
        }

        return ans;
    }
};

如果矩阵有n行m列,此算法时间复杂度为O(mn),空间复杂度为O(m+n)。

解法三:如果存在幸运数,则幸运数有两个性质:
1.只有一个幸运数:对于一个幸运数来说,本行中其他元素都比它大,本列中其他元素都比它小,因此最多只可能出现一个幸运数。如果幸运数为0,则幸运数所在行的数都大于0,所在列的数都小于0,假如有第二个幸运数,由于幸运数需要是本行中最小的数,因此它必须小于本行中第一个幸运数所在列的数,即要小于一个负数,又由于幸运数需要是本列中最大的数,因此它必须大于本列中第一个幸运数所在行的数,即还要大于一个正数,这是不可能的。

2.接1中的假设,由于与幸运数同列的除幸运数外的所有数字都是负数,因此所有每行的最小值中,幸运数所在行是最大的(其他都是负的,幸运数所在行的最小值为0);又由于与幸运数同行的除幸运数外的所有数字都是正数,因此所有每列的最大值中,幸运数所在列是最小的(其他都是正的,幸运数所在列最大值为0),因此幸运数是每列的最大值中最小的,是每行的最小值中最大的。

因此我们可以遍历一遍矩阵,找出所有每行的最小值中最大的值,如果存在幸运数,就是该值,我们再看此数是否是所在列的最大值,如果是,则该数就是幸运数,否则幸运数不存在:

class Solution {
public:
    vector<int> luckyNumbers(vector<vector<int>>& matrix) {
        int rowNum = matrix.size();
        int colNum = matrix[0].size();
        int rowMax = 0, k = -1;
        for (int row = 0; row < rowNum; ++row) {
  			// 找出本行中的最小值
            int curMinIdx = min_element(matrix[row].begin(), matrix[row].end()) - matrix[row].begin();
            // 找出`每行的最小值`中的最大值,并记录其所在列
            if (matrix[row][curMinIdx] > rowMax) {
                rowMax = matrix[row][curMinIdx];
                k = curMinIdx;
            }
        }

        if (k == -1) {
            return {};
        }

        // 看`每行的最小值`中的最大值在其所在列中是否是最大值
        for (int row = 0; row < rowNum; ++row) {
            if (matrix[row][k] > rowMax) {
                return {};
            }
        }

        return {rowMax};
    }
};

如果矩阵有n行m列,此算法时间复杂度为O(mn),空间复杂度为O(1)。

posted @   epiphanyy  阅读(28)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
历史上的今天:
2021-02-20 MySQL必知必会 学习笔记 第十一章 使用数据处理函数
2019-02-20 JAVA中的算术运算符
2019-02-20 JAVA数据类型转换
点击右上角即可分享
微信分享提示