Algorithm 在时间复杂度方面,有多少种方法可以从字符矩阵中以最佳方式形成字符串?
(更新) 我们需要找到从字符矩阵中形成给定字符串的方法的数量 我们可以从矩阵中的任何位置(i,j)开始构词,也可以从矩阵中每个单元格(i,j)的8个方向出发,在任何未访问的方向上构词,即Algorithm 在时间复杂度方面,有多少种方法可以从字符矩阵中以最佳方式形成字符串?,algorithm,data-structures,time-complexity,boggle,Algorithm,Data Structures,Time Complexity,Boggle,(更新) 我们需要找到从字符矩阵中形成给定字符串的方法的数量 我们可以从矩阵中的任何位置(i,j)开始构词,也可以从矩阵中每个单元格(i,j)的8个方向出发,在任何未访问的方向上构词,即 (i + 1, j) (i + 1, j + 1) (i + 1, j - 1) (i - 1, j) (i - 1, j + 1) (i - 1, j - 1) (i, j + 1) (i, j - 1) 样本测试用例: 说明: 使“适合”的方法数量如下所示: (0,0)(0,1)(0,2) (2,1)(2
(i + 1, j)
(i + 1, j + 1)
(i + 1, j - 1)
(i - 1, j)
(i - 1, j + 1)
(i - 1, j - 1)
(i, j + 1)
(i, j - 1)
样本测试用例:
说明:
使“适合”的方法数量如下所示:
(0,0)(0,1)(0,2)
(2,1)(2,0)(3,0)
(2,3)(1,3)(0,4)
(3,1)(2,0)(3,0)
(2,3)(3,4)(3,5)
(2,7)(3,6)(3,5)
(2,3)(1,3)(0,2)
我以一种简单的方式处理解决方案,找到矩阵中每个可能的位置(I,j),通过对矩阵执行DFS搜索,开始从该单元格(I,j)生成字符串,并将从该位置(I,j)生成给定字符串的方法数添加到total_num_ways变量中
伪代码:
但事实证明,这个解决方案的时间复杂度是指数级的,因为我们要到每个可能的n*m位置,然后遍历到每个可能的k(字符串长度)长度路径以形成字符串。
我们如何提高解决方案的效率
#检查给定的(x,y)坐标是否在边界内
#矩阵的
定义单位界限(x、y、行、列):
返回x>=0和x=0和y
不是从矩阵的每个坐标展开路径,而是首先迭代矩阵,以找到与目标字符串中的第一个字母具有相同字母的所有(i,j)坐标。这需要O(n^2)个时间
然后,对于找到的包含目标字符串中第一个字母的每个(i,j)坐标,通过搜索目标字符串中的第二个字母展开路径,并仅展开与第二个字母匹配的路径。对目标字符串中的每个字母重复此操作,以递归方式从起始坐标查找所有有效路径。建议-1:预处理矩阵和输入字符串
我们只关心矩阵的一个单元格,如果该单元格中的字符出现在输入字符串的任何位置。因此,如果输入字符串为“fit”,则我们不关心包含字母“z”的单元格
利用这一点,下面是一个建议
建议2:动态规划 DP在存在最优子结构和重叠子问题的情况下提供帮助。因此,在同一子字符串是多个解决方案的一部分的情况下,使用DP可能会有所帮助 例:如果我们在某个地方找到了“fit”,那么如果相邻单元中有一个“f”,它就可以使用subs
(0,0)(0,1)(0,2)
(2,1)(2,0)(3,0)
(2,3)(1,3)(0,4)
(3,1)(2,0)(3,0)
(2,3)(3,4)(3,5)
(2,7)(3,6)(3,5)
(2,3)(1,3)(0,2)
W = 0
for i : 0 - n:
for j: 0 - m:
visited[n][m] = {false}
W += DFS(i, j, 0, str, matrix, visited);
# Checking if the given (x,y) coordinates are within the boundaries
# of the matrix
def in_bounds(x, y, rows, cols):
return x >= 0 and x < rows and y >= 0 and y < cols
# Finding all possible moves from the current (x,y) position
def possible_moves(position, path_set, rows, cols):
moves = []
move_range = [-1,0,1]
for i in range(len(move_range)):
for j in range(len(move_range)):
x = position[0] + move_range[i]
y = position[1] + move_range[j]
if in_bounds(x,y,rows,cols):
if x in path_set:
if y in path_set[x]:
continue
moves.append((x,y))
return moves
# Deterimine which of the possible moves lead to the next letter
# of the goal string
def check_moves(goal_letter, candidates, search_space):
moves = []
for x, y in candidates:
if search_space[x][y] == goal_letter:
moves.append((x,y))
return moves
# Recursively expanding the paths of each starting coordinate
def search(goal, path, search_space, path_set, rows, cols):
# Base Case
if goal == '':
return [path]
x = path[-1][0]
y = path[-1][1]
if x in path_set:
path_set[x].add(y)
else:
path_set.update([(x,set([y]))])
results = []
moves = possible_moves(path[-1],path_set,rows,cols)
moves = check_moves(goal[0],moves,search_space)
for move in moves:
result = search(goal[1:], path + [move], search_space, path_set, rows, cols)
if result is not None:
results += result
return results
# Finding the coordinates in the matrix where the first letter from the goal
# string appears which is where all potential paths will begin from.
def find_paths(goal, search_space):
results = []
rows, cols = len(search_space), len(search_space[0])
# Finding starting coordinates for candidate paths
for i in range(len(search_space)):
for j in range(len(search_space[i])):
if search_space[i][j] == goal[0]:
# Expanding path from root letter
results += search(goal[1:],[(i,j)],search_space,dict(),rows,cols)
return results
goal = "fit"
matrix = [
'fitptoke',
'orliguek',
'ifefunef',
'tforitis'
]
paths = find_paths(goal, matrix)
for path in paths:
print(path)
print('# of paths:',len(paths))