原创智能优化,原创度检查,一键采集,文章组合(DFS快速入门DFS相关概念在非二叉树上的深度优先搜索)

优采云 发布时间: 2022-03-31 17:28

  原创智能优化,原创度检查,一键采集,文章组合(DFS快速入门DFS相关概念在非二叉树上的深度优先搜索)

  DFS 入门

  DFS 相关概念

  在非二叉树的深度优先搜索中,90% 的问题要么是组合要么是排列。特别是复合类的深度优先搜索问题特别多。排列组合类的搜索问题本质上是一个“隐图”搜索问题。

  隐式图搜索问题:

  如果一个问题没有明确地告诉你什么是点什么是边,而是需要你去搜索,那么它就是一个隐式图搜索问题。所以对于这类问题,首先要分析什么是点,什么是边。

  BFS 与 DFS

  广度优先搜索的空间复杂度取决于宽度

  深度优先搜索的空间复杂度取决于深度

  我们在使用DFS的时候,需要注意三个要素:

  DFS主要可以分为:

  DFS分类问题模型判断条件时间复杂度

  置换问题

  找到所有满足条件的“组合”

  组合中的元素与顺序无关

  O(2^n * n)

  置换问题

  找到满足条件的所有“排列”

  合成中的元素是顺序“相关的”

  O(n! * n)

  DFS时间复杂度的一般计算公式:

  O(计划数量*构建每个计划的时间)

  所以排列问题 = O(n! * n) 组合问题 = O(2^n * n)

  算法模板

  public ReturnType dfs(参数列表){

if(递归出口){

记录答案

return;

}

for(所有的拆解可能性){

修改所有参数

dfs(参数列表);

还原所有被修改过的参数

}

return something;

//很多时候不需要return, 除了分治的写法

  组合类组合DFS

  首先,我们来提一个问题,让大家知道什么叫复合DFS:

  LeetCode 71.子集

  LeetCode 71. 的一个子集

  给定一个整数数组 nums,其元素彼此不同。返回此数组的所有可能子集(幂集)。

  解决方案集不能收录重复的子集。您可以按任何顺序返回解决方案集。

  示例 1:

输入:nums = [1,2,3]

输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

输入:nums = [0]

输出:[[],[0]]

  解决方案:

  class Solution {

public List subsets(int[] nums) {

//首先进行异常检测

if(nums == null){

return results;

}

//创建答案集合

List results = new ArrayList();

Arrays.sort(nums);

dfs(nums, 0 , new ArrayList(), results);

return results;

}

private void dfs(int[]nums,

int startIndex,

ArrayListsubset,

List results){

//直接加加的是reference,这时候后面pop也会让results里的对应pop

results.add(new ArrayList(subset));

for(int i = startIndex; i [1,2]

subset.add(nums[i]);

//去寻找以[1,2] 开头的子集

dfs(nums, i + 1, subset, results);

//[1,2] -> [1]

subset.remove(subset.size() -1 );

}

}

}

  跟进:

  克服上述问题后,请同学们思考这个问题:如果给定的集合是[1,2,2,3],而我输出的子集中不允许有两个[1,2,3],那怎么办我们改变搜索过程?

  LeetCode 90.子集 ll

  LeetCode 90. 子集 ll

  给定一个可能收录重复元素的整数数组 nums,返回该数组的所有可能子集(幂集)。

  说明: 解决方案集不能收录重复的子集。

  例子:

  输入: [1,2,2]

输出:

[

[2],

[1],

[1,2,2],

[2,2],

[1,2],

[]

]

  这个问题是经典的全子集问题的后续问题。稍微想了想,看看这种有重复元素的集合是怎么处理的。

  选择代表:从几个相同数量但顺序不同的小集合中取一个有序集合作为代表,丢弃剩余的无序集合。

  class Solution {

public List subsetsWithDup(int[] nums) {

List results = new ArrayList();

if(nums == null){

return results;

}

Arrays.sort(nums);

dfs(nums, 0 , new ArrayList(), results);

return results;

}

private void dfs(int[]nums, int startIndex, ArrayList subset,

List results){

results.add(new ArrayList(subset));

for(int i = startIndex; i startIndex){

continue;

}

subset.add(nums[i]);

dfs(nums, i + 1, subset, results);

subset.remove(subset.size() -1 );

}

}

}

  有没有可以完成去重工作的数据结构?答案自然是散列,所以我们可以散列所有的集合。每次我们将当前搜索到的子集子集放入结果集子集时,只要把这个集合作为key,如果对应的值不存在,就证明这个集合是一个之前没有出现过的新集合,那么将新集合放入子集中。

<p>public class Solution {

/**

* @param nums: A set of numbers.

* @return: A list of lists. All valid subsets.

*/

public List subsetsWithDup(int[] nums) {

List subsets = new ArrayList();

HashMap visited = new HashMap();

Arrays.sort(nums);

dfs(nums, 0, new ArrayList(), subsets, visited);

return subsets;

}

String getHash(List subset) {

String hashString = "";

for (int i = 0;i

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线