一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情。
题目
给你一个 m * n 的矩阵,矩阵中的数字 各不相同 。请你按 任意 顺序返回矩阵中的所有幸运数。
幸运数 是指矩阵中满足同时下列两个条件的元素:
在同一行的所有元素中最小 在同一列的所有元素中最大
示例 1:
输入:matrix = [[3,7,8],[9,11,13],[15,16,17]] 输出:[15] 解释:15 是唯一的幸运数,因为它是其所在行中的最小值,也是所在列中的最大值。 示例 2:
输入:matrix = [[1,10,4,2],[9,3,8,7],[15,16,17,12]] 输出:[12] 解释:12 是唯一的幸运数,因为它是其所在行中的最小值,也是所在列中的最大值。 示例 3:
输入:matrix = [[7,8],[1,2]] 输出:[7] 解释:7是唯一的幸运数字,因为它是行中的最小值,列中的最大值。
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/lu… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
分析
-
二维数组,遍历时顺序为
第0行->第0-n列->第1行... -
矩阵中的数字,各不相同,每行只有一个最小值、每列只有一个最大值
思路
因为同时满足:
条件1. 在同一行的所有元素中最小
条件2.在同一列的所有元素中最大
的即可视为幸运数,那么只要分别记录两组值,然后求交集即可;
只要在遍历过程记录下每一行的最小值,并用列数做key,当出现某一行的最小值与之前行的最小值同列时,取较大的那一个,作为该列满足条件1的数字中,最大的那一个,保证了每列只会有一个满足条件1的值;
但还还不能保证满足条件2,因为可能该列有更大的数字但不满足条件1的,所以需要再记录一下每一列的最大值,仍然以列数作为key,这样每列就会有一个满足条件2的值;
然后再进行比对,若最小值集的某一列的值等于最大值集的某一列的值时(矩阵中数字各不相同),即可视为该数字为幸运数字
代码实现
/**
* @param {number[][]} matrix
* @return {number[]}
*/
var luckyNumbers = function(matrix) {
const minMap = {}
const maxMap = {}
for(let i = 0;i<matrix.length;i++){
let tempMin = Infinity; // 当前行的最小值,初始化为无穷大,保证大于任意一个值
let minIdx; // 当前行最小值对应的列数
for(let j = 0;j<matrix[i].length;j++){
if(matrix[i][j]<tempMin){ // 小于当前该行最小值
tempMin = matrix[i][j];
minIdx = j;
}
// 记录当前行最大值,用列数做key,若同列已有一个满足条件2,取小的那个
if(!maxMap[j] || matrix[i][j]>maxMap[j]){
maxMap[j] = matrix[i][j];
}
}
if(minMap[minIdx]){ // 同列已经有一个满足条件1的值,取大的那个
minMap[minIdx] = Math.max(minMap[minIdx],tempMin);
}
else
minMap[minIdx] = tempMin;
tempMin = Infinity; // 重置临时参数
minIdx = null
}
// 遍历满足条件1的值所在的列,若满足条件2的该列值等于该值时,即为幸运数
return Object.keys(minMap).filter(k=>minMap[k] === maxMap[k]).map(k=>minMap[k])
};
这里有一个比较奇怪的点解释一下,记录最小值时,需要临时变量来记录当前行的最小值,这是为了保证筛选出满足条件1的值(以列数作为key,没有办法保证同行覆盖),若该列已有一个满足条件1,则进一步筛选选出较大的那个;
而记录最大值时,无需在行内比较,以列数作为key,所以不需要临时变量记录,只要行内的值大于已记录的该列的最大值时,即可视为满足条件2(后续如果有更大的会覆盖)
结果
空间略大了,想想怎么优化