在2D数组中搜索序列(仅访问每个条目一次)

时间:2016-09-20 01:03:02

标签: algorithm search matrix

这是书中的一个问题"编程访谈的元素" (17.5)。问题是:

当A是矩阵而S是整数数组时,我们说S出现在A中,如果你可以从A中的某个条目开始并按照S规定的顺序遍历A中的相邻条目。相邻的条目是顶部,底部,左和右。

例如,如果 A =

[1 2 3

3 4 5

5 6 7]

S = [1 3 4 6]

然后S在A中,因为A [0] [0] = 1,A [1] [0] = 3,A [1] [1] = 4,A [2] [1] = 6 < / p>

但如果S = [1 2 3 4]则S不在A中。

如果可以多次访问A中的条目,我理解如何使用递归来解决问题。

但是如果有一个额外的约束条件,我可以有效地解决问题,每次最多可以访问一次?

2 个答案:

答案 0 :(得分:1)

这是直接的Depth First Search(DFS)问题。

以下是算法的概要:

  1. 查找所有等于S [0]的元素(序列中的第一个数字)
  2. 对于未访问的步骤1中找到的所有元素,请执行DFS,将已标记的节点视为已访问。 仅访问相邻节点,如果未访问它并且它是序列中的下一个数字
  3. 在步骤2中,每个节点最多访问一次。例如,一个棘手的案例就像

    S = [1,2,3,4]
    
    A = [1,2,1]
        [2,3,2]
        [3,2,1]
    

    这种情况没有答案,所有节点都只访问过一次:

    // After first DFS starting at [0,0],  1 = visited, 0 = not visited
    V = [1,1,0]
        [1,1,0]
        [1,0,0]
    // After second DFS starting at [0,2], 1 = visited, 0 = not visited
    V = [1,1,1]
        [1,1,1]
        [1,0,0]
    // After third DFS starting at [2,2], 1 = visited, 0 = not visited
    V = [1,1,1]
        [1,1,1]
        [1,1,1]
    // Done, complexity = O(N*M) where the matrix is of size N X M
    

    以下是用C ++编写的示例代码:http://ideone.com/ganX9Z

答案 1 :(得分:0)

如果将 visit 解释为“未按给定序列访问单元”,即在算法期间可以多次访问该单元,那么我可以想到的最佳解决方案是我相信指数时间复杂度。

要点是要跟踪给定路径上访问的单元格:

from typing import Set, Tuple

def is_pattern_contained_in_grid(grid, S):
    def traverse(x, y, s_idx, visited: Set[Tuple[int,int]]):
        if (s_idx == len(S)):
            return True

        if ((x, y) in visited
            or not( x >= 0 and y >= 0 and x < n and y < m)
            or grid[x][y] != S[s_idx]):
            return False

        for adj_x, adj_y in ((x + 1, y),
                        (x - 1, y),
                        (x, y + 1),
                        (x, y - 1)):
            if (traverse(adj_x, adj_y, s_idx + 1, visited.union({(x,y)}))):
                return True

        return False


    if (not S):
        return True

    n = len(grid)
    m = len(grid[0])
    for i in range(n*m):
        x = i % n
        y = i // n
        if (traverse(x, y, 0, set())):
            return True

    return False

# Some examples
print(is_pattern_contained_in_grid([[0,0,0,0],[0,1,3,1],[0,3,4,0],[1,5,6,7]], [1,5,3,1,3,1]))
print(is_pattern_contained_in_grid([[0,0,0,0],[0,1,3,7],[0,3,4,0],[1,5,6,7]], [1,5,3,1,3,1]))
print(is_pattern_contained_in_grid([[0,0,0,0],[0,1,3,1],[0,3,4,0],[1,5,6,7]], [1,5,3,5,6]))