这是书中的一个问题"编程访谈的元素" (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中的条目,我理解如何使用递归来解决问题。
但是如果有一个额外的约束条件,我可以有效地解决问题,每次最多可以访问一次?
答案 0 :(得分:1)
这是直接的Depth First Search(DFS)问题。
以下是算法的概要:
在步骤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]))