1380. 矩阵中的幸运数(暴力)

188 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

每日刷题第72天 2021.03.31

1380. 矩阵中的幸运数

题目描述

  • 给你一个 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
  • 找到比当前最小值还要大的数,则当前最小值不是幸运数,不计入最终的结果;
  • 没有找到比当前最小值还要大的数,则当前的最小值就是幸运数,计入最终结果即可。

常规标记法:

  • 遍历数组,记录每行的最小值和每一列的最大值
  • 遍历数组,如该数字等于该行最小值且等于该列最大值,将该值保存到结果中

取巧方法:

  • 取出数组的一行,找到该行的最小值,记录最小值的位置
  • 判断该最小值是否是该列的最大值,若是,将该值保存到结果中

优化

  • 实际上,无需使用额外的空间来记录每行、每列的最值
  • 这是因为当我们遍历二维数组找到当前行的最小值时,可以直接再去判断该元素是否是其所在列的最大值。此时可以在遍历过程中判断是否是幸运数,并添加到结果集中
  • 优化后复杂度分析:mn 分别是矩阵的行数、列数
    • 时间复杂度: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语句也没用,因此需要将结果记录下来,最后再输出。