逻辑矩阵如何有效查找具有真实值的行/列

时间:2019-03-10 20:59:27

标签: algorithm matrix data-structures time-complexity

我正在为下一个谜语寻找有效的解决方案:

  1. 我有一个( n * n )大小的逻辑矩阵,其中填充了 false
  2. 我需要创建一个将参数设为零或一的函数它将全部移位 矩阵中的值向左移动(表示第一个 第一行中的元素被删除,最后一行中的最后一个元素 row是我们的新位),如果我们的行/列是,则返回true 矩阵仅包含一个人的值。

对数据结构没有限制。

我在javascript中的幼稚解决方案:

const next = (bit, matrix) => {
  matrix.shift()
  matrix.push(bit);

  const matrix_size = Math.sqrt(matrix.length);

  let col_sum = 0;
  let row_sum = 0;

  for (let i = 0; i < matrix.length; ++i) {
    col_sum = matrix[i];
    row_sum += matrix[i];

    if ((i + 1) % matrix_size === 0) {
      if (row_sum === matrix_size) return true;

      row_sum = 0;
    }

    for (let j = i + matrix_size;j < (i + ((matrix_size * matrix_size) - 1)); j += matrix_size) {
      col_sum += matrix[j];
    }

    if (col_sum === matrix_size) return true;
  }

  return false;
}

我使用1d数组作为数据结构,但实际上并不能帮助我减少时间复杂度。

喜欢听到一些想法:)

1 个答案:

答案 0 :(得分:3)

让我们考虑以下示例矩阵:

[0, 0, 0, 0,
 0, 0, 0, 0,
 0, 0, 1, 1,
 1, 1, 1, 1]

并推零16次。
然后,将获得False,True,True,True,False,True,True,True,False,True,True,True,False,False False和False。
存在循环行为(False,True,True,True)。
如果连续的长度是固定的,则不必每次更新都重新计算。
更新矩阵后,可以更改左上角和右下角连续字符的长度,并且可能需要更新循环存储器。
维持连续的序列,保持受序列影响的循环行为总数,行的复杂度将在O(1)中。

在使用列的情况下,让matrix[cur]=bitcur = (cur+1)%(matrix_size*matrix_size)代替cur来表示O(1)作为矩阵的实际左上角。
维持每一列的col_sum,维持满足全条件的总数,复杂度将为class Matrix: def __init__(self, n): self.mat = [0] * (n*n) self.seq_len = [0] * (n*n) self.col_total = [0] * n self.col_archive = 0 self.row_cycle_cnt = [0] * n self.cur = 0 self.continued_one = 0 self.n = n def update(self, bit): prev_bit = self.mat[self.cur] self.mat[self.cur] = bit # update col total col = self.cur % self.n if self.col_total[col] == self.n: self.col_archive -= 1 self.col_total[col] += bit - prev_bit if self.col_total[col] == self.n: self.col_archive += 1 # update row index # process shift out if prev_bit == 1: prev_len = self.seq_len[self.cur] if prev_len > 1: self.seq_len[(self.cur + 1) % (self.n * self.n)] = prev_len-1 if self.n <= prev_len and prev_len < self.n*2: self.row_cycle_cnt[self.cur % self.n] -= 1 # process new bit if bit == 0: self.continued_one = 0 else: self.continued_one = min(self.continued_one + 1, self.n*self.n) # write the length of continued_one at the head of sequence self.seq_len[self.cur+1 - self.continued_one] = self.continued_one if self.n <= self.continued_one and self.continued_one < self.n*2: self.row_cycle_cnt[(self.cur+1) % self.n] += 1 # update cursor self.cur = (self.cur + 1) % (self.n * self.n) return (self.col_archive > 0) or (self.row_cycle_cnt[self.cur % self.n] > 0) def check2(self): for y in range(self.n): cnt = 0 for x in range(self.n): cnt += self.mat[(self.cur + y*self.n + x) % (self.n*self.n)] if cnt == self.n: return True for x in range(self.n): cnt = 0 for y in range(self.n): cnt += self.mat[(self.cur + y*self.n + x) % (self.n*self.n)] if cnt == self.n: return True return False if __name__ == "__main__": import random random.seed(123) m = Matrix(4) for i in range(100000): ans1 = m.update(random.randint(0, 1)) ans2 = m.check2() assert(ans1 == ans2) print("epoch:{} mat={} ans={}".format(i, m.mat[m.cur:] + m.mat[:m.cur], ans1))

pyinstaller