【问题标题】:DFS to check if characters exist on diagonals in 2d gridDFS 检查二维网格中的对角线上是否存在字符
【发布时间】:2020-01-18 16:37:22
【问题描述】:

我正在编写一个算法来检查二维数组是否具有字符序列。我的算法适用于水平和垂直搜索,但不适用于对角线:

board = [
    ['Z', 'B', 'N', 'O', 'N', 'O'],
    ['Z', 'B', 'O', 'N', 'N', 'Z'],
    ['B', 'O', 'B', 'B', 'N', 'B'],
    ['O', 'N', 'O', 'N', 'N', 'N'],
    ['Z', 'Z', 'Z', 'Z', 'B', 'O'],
    ['B', 'Z', 'O', 'Z', 'B', 'N']
]

def dfs(board, word):
    if not board:
        return False
    N,M = len(board), len(board[0])
    stack = []
    for i in range(N):
        for j in range(M):
            if board[i][j] == word[0]:
                stack.append((i,j,0,{(i,j)}))
    while stack:
        i,j,step,visit=stack.pop()
        step+=1
        if step==len(word):
            return True        
        for (ni,nj) in [(i+x,j+y) for x,y in [(0,1), (0, -1), (1,0), (-1,0)]]:
            if (ni,nj) not in visit and 0<=ni<N and 0<=nj<M and board[ni][nj] == word[step]:
                stack.append((ni,nj,step,visit.union({(ni,nj)})))
    return False

对于输入 ZZZZNNNNOOOO,我的函数 DFS 应该返回 True,但 OOOO 不起作用 - 对角线步骤不起作用。

我该如何解决?

【问题讨论】:

  • 您只有一种情况需要解决(例如从左上角开始的对角线),因为所有其他三种情况都可以通过相同的算法访问,并且只需左右、上下或两个都。而且您可能可以根据搜索的字符串的长度进一步限制(我已经看到这个基于 TicTacToe 的示例在采访中要求)

标签: python algorithm depth-first-search


【解决方案1】:

线

for (ni,nj) in [(i+x,j+y) for x,y in [(0,1), (0, -1), (1,0), (-1,0)]]:

仅将邻居视为四个基本方向。要包括对角线,我们应该有 8 个邻居:

directions = [
    (0, 1), (0, -1), (1, 0), (-1, 0), 
    (-1, -1), (1, 1), (-1, 1), (1, -1)
]

for ni, nj in [(i + x, j + y) for x, y in directions]:

修改后,算法探索对角线:

print(dfs(board, "OOOO")) # => True
print(dfs(board, "NBNZ")) # => True
print(dfs(board, "BNZO")) # => True

如果您打算将搜索限制在直线方向(从左上角删除 "ZBOB" 之类的内容),则 DFS 方法不会有太大帮助。您可以在所有可能的方向上简单地从每个方格进行迭代,而无需进行任何转弯,并在第一个不匹配的字母上尽早放弃。您当前的算法允许转弯,即使没有修改对角线,所以我假设您希望保留这种许可逻辑。

【讨论】:

  • 伙计,你是个怪物! :D 是否可以使用多个单词进行搜索?现在,我正在为每个单词做一个循环
  • 嗯,可能有一种最佳方法可以做到这一点,但在如此小的网格上可能并不值得付出努力。过早的优化等等。在您遇到性能问题之前,我只会遍历您要检查的所有单词并为每个单词对网格进行 DFS。你可以在单词之间多次使用字母吗?当然,如果你想在一个巨大的网格上检查一百万个单词,那可能需要一些思考(并为此提出一个特殊问题)。
  • 等一下,让我解释一下我的意思:是否可以在任何方向上找到相同的 4 个字母的任意组合?又有多少组合呢?我的意思是我想知道矩阵中有多少四个字母的组合。
  • 当然,似乎可行,但就要求而言仍存在不确定性。 “任何方向”都可以包括弯曲还是必须是直的?网格中的字母是否可以多次重复使用(一个单词和单词之间)?性能有多重要(例如,网格很大吗?)。这与您在上面提出的问题相去甚远,所以我会自己尝试一下,如果您遇到问题,请提出一个新问题。如果您最终这样做,我会尝试看看它并提供帮助。一个起点可能只是 itertools.combinations 并在循环中使用现有的 DFS。
  • 太棒了!我会看看 itertools.combinations!
猜你喜欢
  • 2017-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-15
  • 2019-06-16
  • 2023-03-28
  • 2022-01-05
相关资源
最近更新 更多