[路飞]_今夜转矩阵

414 阅读2分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

519. 随机翻转矩阵

题目

给你一个 m x n 的二元矩阵 matrix ,且所有值被初始化为 0 。请你设计一个算法,随机选取一个满足 matrix[i][j] == 0 的下标 (i, j) ,并将它的值变为 1 。所有满足 matrix[i][j] == 0 的下标 (i, j) 被选取的概率应当均等。

尽量最少调用内置的随机函数,并且优化时间和空间复杂度。

实现 Solution 类:

  1. Solution(int m, int n) 使用二元矩阵的大小 m 和 n 初始化该对象
  2. int[] flip() 返回一个满足 matrix[i][j] == 0 的随机下标 [i, j] ,并将其对应格子中的值变为 1
  3. void reset() 将矩阵中所有的值重置为 0

哈希表

首先如果使用mnm*n这个复杂度的二维数组,再随机返回i,j和操作二维数组数据;思路没有问题,但是时间复杂度肯定非常高;

所以为了降低复杂度可以将二维数组降低为一维数组;

随机的时候,随机一维数组长度;得到一个随机值;数组长度-1;

为什么数组长度-1;

因为要保证下次随机不包含本次已经随机到的数;

哪还有一个问题,如果数组长度为20;第一次随机到7,数组长度-1为19;第二次在随机得到7呢?

解答:第一次随机到7,将20放在map中,map中数据结构key为7,value为20;第二次在随机到7,将20丢出去;

为什么把20丢出去?因为在第二次随机的最大值是19,不可能是20,以后都不可能,但是可以是7,实际上是将7代替了已经随机不到的20;7可以随机得到,但是永远不能再次出现

将20丢出去,再将19放进来。

因为第3次随机的时候最大值已经是18了,这是的7就代表了19;

你理解了吗?

动态图

111.gif

图片

动态图动的太快了,不太容易看到;后续会改进; 可以看下面的的图了解具体思路

图中注释非常重要

未命名.001.jpeg

未命名.002.jpeg

未命名.003.jpeg

未命名.004.jpeg

未命名.005.jpeg

未命名.006.jpeg

未命名.007.jpeg

代码#

根据上述图片思路编辑代码如下

/**
 * @param {number} m
 * @param {number} n
 */
var Solution = function (m, n) {
  this.m = m
  this.n = n
  this.total = m * n
  this.map = new Map()
}

/**
 * @return {number[]}
 */
Solution.prototype.flip = function (index) {
  const key = [8, 8, 4, 7, 7][index]
  this.total--
  const idx = this.map.get(key) || key
  this.map.set(key, this.map.get(this.total) || this.total)
  console.log('map', key, this.map)
  return [Math.floor(idx / this.n), idx % this.n]
}

/**
 * @return {void}
 */
Solution.prototype.reset = function () {
  this.total = this.m * this.n
  this.map.clear()
}