回溯树求集合全排列和所有子集
本公众号主要推送关于对算法的思考以及应用的消息。算法思想说来有,分而治之,深度搜索,动态规划,回溯,贪心等,结合这些思想再去思考如今很火的大数据,云计算和机器学习,是不是也别有一番风味呢? 踏上算法之路,风景这边独好!
01
—
通过这篇文章,你学到什么
通过这篇文章,我们可以进一步体会到深度优先搜索算法在具体问题中的应用,通过详细地示意图,深刻明白递归调用时的进栈,出栈过程;最后通过Leetcode 相似解法的题目进一步加深对深度搜索算法的理解。
02
—
搜索算法
搜索算法,常见的几种形式,深度优先,广度优先,二分搜索,应用搜索算法的前提是求解空间是有限的,然后在这个空间中找出满足题意的解。有些问题如果能用二分搜索,那是最高效的,因为每次都会使求解空间减掉一半。
03
—
DFS
Depth first search algorithm,它是首先沿着深度方向搜索,然后再在广度方向搜索的。例如,要求某个序列的全排列,就可以用深度优先搜索。
04
—
全排序深度搜索算法
1 某个序列的全排序算法题目
The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the permutations in order, We get the following sequence (ie, for n = 3): "123" "132" "213" "231" "312" "321"
2 题目分析
如何写出深度优先搜索的代码呢?
- 首先我们拿出元素1,然后在1,2,3 这个深度方向寻找,找到满足题意的解有两个,1,2,3,和1,3,2;
- 然后再在广度方向上搜索,此时的元素为2,再在1,2,3 深度方向上搜索,得到满足题意的解,2,1,3和2,3,1,
- 最后,在广度方向上搜索到3,再在1,2,3 深度方向上搜索,满足题意的解为 3,1,2 和 3,2,1。
3 源码实现
public class Solution
{
public IList<IList<int>> GetPermutation(int n)
{
IList<IList<int>> rslt = new List<IList<int>>();
dfs(rslt, new List<int>(),1,n);
return rslt;
}
// start 是dfs抽出的一个关键参数
private void dfs(IList<IList<int>> rslt,
List<int> curItem,
int start,
int digits)
{
//找到一个解
if (curItem.Count == digits)
{
rslt.Add(new List<int>(curItem));
return;
}
//广度方向搜索
for (int i = 1; i <= digits; i++)
{
//跳过重复元素
if (curItem.Contains(i))
continue;
curItem.Add(i);
//深度方向上的递归
dfs(rslt, curItem, i,digits);
//后进栈的元素优先出栈
curItem.RemoveAt(curItem.Count - 1);
}
}
}
05
—
图解源码
dfs递归调用的进、出栈示意图
dfs 在深度方向递归进、出栈过程,广度方向首先遍历到1,但是不展开,而是在深度方向展开,1,2,3 的 dfs 依次入栈,出栈顺序依次为 3,2,1,1,如下图所示,
然后再在广度方向上搜索【补充,可以看出深度优先搜索在前,广度方向上搜索在后,所以叫做 DFS】,此时 广度方向 for 遍历到 i = 2,然后再在深度方向搜索,出栈顺序依次为 3,2,1,2,如下图所示,
同理,广度方向搜索到 i=3,然后再在深度方向搜索,出栈顺序依次为 3,2,1,3,如下图所示,
dfs 终止
06
—
融会贯通
应用这个深度搜索算法思想模板可以解决 LeetCode 上的一类题目,这些题目的解法与本文介绍的全排序搜索算法极为相似,大家不妨看一看,写一写,彻底贯通这个深度搜索算法思想模板。
1 Leetcode 78. Subsets
Given a set of distinct integers, nums, return all possible subsets. Note: The solution set must not contain duplicate subsets. For example, If nums = [1,2,3], a solution is:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
2 Leetcode 90. Subsets II
Given a collection of integers that might contain duplicates, nums, return all possible subsets.Note: The solution set must not contain duplicate subsets. For example, If nums = [1,2,2], a solution is:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
3 Leetcode 47. Permutations II
Given a collection of numbers that might contain duplicates, return all possible unique permutations.For example, [1,1,2] have the following unique permutations:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
4 Leetcode 131. Palindrome Partitioning
Given a string s, partition s such that every substring of the partition is a palindrome. Return all possible palindrome partitioning of s. For example, given s = “aab”, Return
[ [“aa”,”b”], [“a”,”a”,”b”] ]
看看 Leetcode 上这些应用了 DFS 的题目,这些题目与 讲解的那道题思路非常相似,灵活运用的这个思考过程还是很重要的,仔细体会下吧。
以上答案的链接,请参考如下引用:
http://blog.csdn.net/column/details/14761.html?&page=1
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Flutter 步骤进度组件
- 慌:一次订单号重复,差点被开除
- Flutter 分页功能表格控件
- 3分钟短文:Laravel 从软删除说到模型作用域的概念
- Flutter 系统是如何实现ExpansionPanelList的
- Flutter 粘合剂CustomScrollView控件
- Flutter 1.17版本重磅发布
- Flutter 首页必用组件NestedScrollView
- 【Flutter实战】文本组件及五大案例
- 你真的会用Flutter日期类组件吗
- 【Flutter实战】图片组件及四大案例
- Flutter 标签类控件大全Chip
- 【Flutter实战】六大布局组件
- 【Flutter实战】定位装饰权重组件及柱状图案例
- Flutter为什么使用Dart?