【问题标题】:logical matrix how to find efficiently row/column with true value逻辑矩阵如何有效地找到具有真值的行/列
【发布时间】:2019-03-10 20:59:27
【问题描述】:

我正在努力为下一个谜题找到一个有效的解决方案:

  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;
}

我使用一维数组作为数据结构,但它并不能真正帮助我降低时间复杂度。

喜欢听到一些想法:)

【问题讨论】:

    标签: algorithm matrix data-structures time-complexity


    【解决方案1】:

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

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

    并按 16 次归零。
    那么,就会得到假、真、真、真、假、真、真、真、假、真、真、真、假、假、假、假。
    存在循环行为(假、真、真、真)。
    如果连续的长度是固定的,则不需要每次更新都重新计算。
    更新了矩阵,左上和右下的连续的长度可以改变,可能需要更新循环内存。
    保持连续的序列,保持受序列影响的循环行为的总数,行的复杂度将在O(1)

    如果是列,而不是移位和推动,让matrix[cur]=bitcur = (cur+1)%(matrix_size*matrix_size)cur 表示为矩阵的实际左上角。
    维护每列的col_sum,维护满足全1条件的总数,复杂度为O(1)

    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))
    

    【讨论】:

    • 哇,谢谢!!:)
    • @YochaiAkoka 和 machy(以及任何其他可以提供帮助的读者)我很困惑 :) 例如,仅查看行 - 如果我们有一个 N*N 矩阵,并且我们有一个任意数字在从右下角开始且没有定时模式的 N 个连续 1 的不同块中,我们如何在 O(1) 中跟踪这些连续块中的哪一个可能随时占据一整行?你能示范一下吗?
    • @גלעדברקן 我已经附加了代码,即使没有足够的评论......代码是根据基本思想编写的。对于 4x4 大小的矩阵,从 3 到 4 的增长序列会影响循环行为,4 到 5、5 到 6、6 到 7 也会影响,但 7 到 8 不会影响。因为序列长或等于 7 使得条件随时为真。 if self.n &lt;= self.continued_one and self.continued_one &lt; self.n*2: 反映了这个想法。
    • 这个答案太棒了。如果可以的话,我会再投票一次:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 2021-05-10
    • 2017-04-01
    • 1970-01-01
    • 2011-03-07
    相关资源
    最近更新 更多