返回
LeetCode 902:采用记忆化 DFS 方法破解 Numbers At Most N Given Digit Set (Python)
闲谈
2024-01-20 02:17:38
问题概述:
LeetCode 902. Numbers At Most N Given Digit Set 问题如下:
给定一个正整数 n 和一个数字集合 digits,要求你计算出小于等于 n 的所有正整数中,有多少个正整数的数字全部来自数字集合 digits。
例如:
digits = [1,3,5,7]
n = 100
在这种情况下,小于等于 100 且数字全部来自集合 digits 的正整数有:
1, 3, 5, 7, 11, 13, 15, 17, 31, 33, 35, 37, 51, 53, 55, 57, 71, 73, 75, 77
因此,最终结果为 20。
记忆化 DFS 方法解析:
为了解决这个问题,我们将采用记忆化 DFS 的方法。DFS(深度优先搜索)是一种广泛应用于计算机科学中的递归算法,它通过遍历节点的所有可能路径来搜索解空间,并在每次搜索时记录已访问过的节点。记忆化是将已经计算过的结果存储起来,以便下一次遇到相同参数时可以快速检索到之前计算过的结果,从而避免重复计算。结合 DFS 和记忆化,我们将能够高效地计算出小于等于 n 且数字全部来自集合 digits 的正整数的个数。
以下步骤概述了记忆化 DFS 的基本流程:
- 定义一个函数 f(i, prev, used),其中 i 表示当前处理的数字的索引,prev 表示前一个数字,used 表示当前已使用的数字集合。
- 当 i 等于数字集合 digits 的长度时,如果 used 包含所有数字,则结果加一,否则返回零。
- 否则,对于数字集合 digits 中的每个数字 d,如果 d 不等于 prev 并且 d 不在 used 中,则调用 f(i+1, d, used + {d})。
- 将结果返回给调用者。
使用记忆化技术,我们将能够存储已经计算过的结果,避免重复计算。这将大大提高算法的效率,使其能够在合理的时间内求解问题。
Python 实现:
def num_of_numbers(n, digits):
memo = {}
def dfs(i, prev, used):
if i == len(digits):
if set(digits) == used:
return 1
else:
return 0
if (i, prev, tuple(used)) in memo:
return memo[(i, prev, tuple(used))]
result = 0
for d in digits:
if d != prev and d not in used:
result += dfs(i + 1, d, used + {d})
memo[(i, prev, tuple(used))] = result
return result
return dfs(0, -1, set())
if __name__ == "__main__":
digits = [1, 3, 5, 7]
n = 100
result = num_of_numbers(n, digits)
print(f"The number of numbers at most {n} with digits from {digits} is {result}")
结论:
我们已经成功地利用记忆化 DFS 方法解决了 LeetCode 902. Numbers At Most N Given Digit Set 问题。该方法通过将已经计算过的结果存储起来,避免重复计算,大大提高了算法的效率。Python 代码的实现也清晰明了,便于理解和修改。希望这篇博文能帮助读者更好地理解记忆化 DFS 方法,并将其应用到更多的算法问题中。