常见搜索问题的迭代解法

从搜索树结构上讲,这类问题所有解的构造方式呈现 BFS 的分层结构,可以手动建立分层处理的机制处理。与之相对的,最常见的递归解法是从 DFS 的角度去探索状态空间。

搜索问题的迭代解法主要分这么两种,取决于最终解的构造方式,也即 F(n) 和 F(n - 1) 之间的关系。

  • append 类

    • 比如 subsets 中,每次迭代出现的新解,都是由新元素 append 到已知解的后面构造出来的;(不过所有过程中的已知解都留下来了)

    • 在 Phone letter combination 里也是一个道理,只不过这次我们不存过渡结果,只保留最后一层。

  • insert 类

    • 比如 permutation ,这里解的构造方式靠 "insert",所以 BFS 分层的搜索结构中,会反复出现靠插入构造出的新结果。

这题三种解法的分析:

http://bangbingsyb.blogspot.com/2014/11/leetcode-subsets-i-ii.htmlarrow-up-right

迭代:

位运算:

由于S[0: n-1]组成的每一个subset,可以看成是对是否包含S[i]的取舍。S[i]只有两种状态,包含在特定subset内,或不包含。所以subset的数量总共有2^n个。所以可以用0~2^n-1的二进制来表示一个subset。二进制中每个0/1表示该位置的S[i]是否包括在当前subset中。

讨论帖子:

https://discuss.leetcode.com/topic/6377/my-ac-simple-iterative-java-python-solutionarrow-up-right

http://bangbingsyb.blogspot.com/2014/11/leetcode-permutations-i-ii.htmlarrow-up-right

想迭代做这题,要先从理解为什么对于 cardinality = n 的集合,其总共的 permutation = n! 开始,permutation 的构造过程是:

  • 第 n 层 permutation 的每个解中,有 n 个元素;

  • 从n = 1 开始,放入第 1 个元素;

  • 下一层要新加入的元素是 n + 1,在第 n + 1 层;

  • 我们要从 n 层的所有结果中,插入所有可以插入的位置,对于每一个 size = n 的解,可插入位置为 n + 1 个;

  • 于是每一层新得到的解的总数 F(n + 1) = F(n) * (n + 1), 可知 F(n) = n!

  • 注意点1:一开始要加个 {} 进去,要么无法起始;

  • 注意点2:List.add(index, ele) 记熟,不是 insert

  • 注意点3: 插入范围要比 prevList.size() 大一个,所以具体有效的插入 index 是【0, prevList.size()】 的闭区间,

Last updated