Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
每日刷题第72天 2021.03.31
1380. 矩阵中的幸运数
- leetcode原题链接:leetcode-cn.com/problems/lu…
- 难度:简单
- 方法:暴力模拟
题目描述
- 给你一个 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 是唯一的幸运数,因为它是其所在行中的最小值,也是所在列中的最大值。
解题思路
- 暴力模拟
- 首先使用map集合,将每一行中最小的数组的下标记录下来。
- 再用每一行最小的下标和其所在的每一列的值进行比较(封装函数
isLucky) - 找到比当前最小值还要大的数,则当前最小值不是幸运数,不计入最终的结果;
- 没有找到比当前最小值还要大的数,则当前的最小值就是幸运数,计入最终结果即可。
常规标记法:
- 遍历数组,记录每行的最小值和每一列的最大值
- 遍历数组,如该数字等于该行最小值且等于该列最大值,将该值保存到结果中
取巧方法:
- 取出数组的一行,找到该行的最小值,记录最小值的位置
- 判断该最小值是否是该列的最大值,若是,将该值保存到结果中
优化
- 实际上,无需使用额外的空间来记录每行、每列的最值
- 这是因为当我们遍历二维数组找到当前行的最小值时,可以直接再去判断该元素是否是其所在列的最大值。此时可以在遍历过程中判断是否是幸运数,并添加到结果集中
- 优化后复杂度分析:
m和n分别是矩阵的行数、列数- 时间复杂度:
O(m*Max(n, m)) - 空间复杂度:
O(1)
- 时间复杂度:
AC代码
var luckyNumbers = function(matrix) {
// [8,6]
// [5,7]
// 先将每一行最小的标记,记录下标
// 循环遍历是否为当前这一列最大的值,是输出;否,跳出,执行下一层
let lenR = matrix.length;
let lenC = matrix[0].length;
let index = new Map();
let min = Infinity;
let ans = [];
// 记录每一行最小值的下标
for(let i = 0; i < lenR; i++) {
min = Infinity;
for(let j = 0; j < lenC; j++) {
if(matrix[i][j] < min){
min = matrix[i][j];
index.set(i,j);
}
}
}
// console.log(index);
function isLucky (key,value) {
for(let i = 0; i < lenR; i++){
if(key == i) continue;
if(matrix[i][value] > matrix[key][value]) return false;
}
return true;
}
// key => i value => j
index.forEach((value,key) => {
// console.log(key,value);
if(isLucky(key,value)) ans.push(matrix[key][value]);
});
return ans;
};
总结
- forEach循环是不能中断的,即使你在里面写了
return语句也没用,因此需要将结果记录下来,最后再输出。