DFS template and summary
最近一直在学习Deep Frist Search,也在leetcode上练习了不少题目。从最开始的懵懂,到现在遇到问题基本有了思路。依然清晰的记得今年2月份刚开始刷题的时做subsets的那个吃力劲,脑子就是转不过来到底该如何的递归,甚至试过使用debugger一步步的来看看堆栈到底是如何调用和返回的。经过了几个月的训练后,答题有了一些心得,记录下来,作为总结。
递归函数的整体结构:
返回值。进入入递归函数的第一件事就是写出递归终止的条件。通常递归终止的条件分为两类:
(1)有一个深度的标准,例如N-Queen问题,当我们递归的检测完第N个皇后,就到达来递归返回的条件,此时,将此次递归的结果作为一个解决方案存储。
(2)到达一个序列(数组/字符串)vector/string.size()的位置,例如subsets,permutation和word break ii的问题,当传递的参数已经无法索引数组/字符串的值时退出递归。
是否进行prune的操作。这个操作并不是一定会存在的。当需要prune的时候,通常是遇到了效率问题。当输入问题的规模非常大,存储之前已经做过检测或者得出结果的递归位置会大大降低递归的工作量。这个时候我们通常会利用一些数据结构。最简单的就是一个数组,复杂一点的会是一个hash table(word break ii in leetcode)。
本层的递归处理以及下一层次的递归调用。这一部分是递归的核心,如果这一部分模型处理正确,递归的调用就成功了90%(很像如果能写出动态规划的状态方程的感觉)。
返回值。最后的return,连同递归的处理和调用,具体内容会这下面详细阐述。
递归函数的类型:
总的来说DFS的函数分为两种类型,有返回值和没有返回值。递归的层次都是通过一个参数传递到函数内部,这两种函数的编写有区别,虽然都是DFS,但思维方式却是不一样。
对于无返回值的DFS函数,通常我们是将需要获取的值作为引用类型的参数传递到函数内部,当到达DFS函数终止的条件时我们获取想要得到的值,例如N-Queen,subsets, permutations等经典的问题。这是一种从上向下的思维模式。这种函数适用于求所有可能的解的问题。通常是先对该层的问题进行处理,然后再进入下一个层次的递归。当到达递归终止的条件时存储结果。然后再逐层的返回,通常会恢复该层这遍历之前的状态,为的是下一个递归。
以下为这种递归的模板:
void DFS_no_return(vector<TYPE>& solution_set, TYPE& solution, int idx){
// DFS terminate condition
// Normally there are two major categories
// One is for some number, already reach this depth according to the question, stop
// get to the end of an array, stop
if(idx == n || idx == (vector/string).size()){
solution_set.push_back(solution);
return;
}
// very seldom only when our program met some efficiency problem
// do prune to reduce the workload
// no need do DFS if we already get the value of current element, just return
if(hash_table[input] != hash_table.end()){
return;
}
for(int i = ; i < n; i++){
if(visited[i] == ){
// do something for current level process
visited[i] = ;
// for next level DFS
DFS_no_return(solution_set, solution, idx + );
// return from lower level DFS and restore the status for next DFS
visited[i] = ;
}
}
return;
}
对于有返回值的DFS来说,我们需要获得的值是递归函数的返回值。与无返回值的递归函数相比,最大的一个区别是该类递归函数在递归调用返回之后处理该层的递归值。将从低层次递归返回的值结合本层的值处理,然后再返回给上一层递归函数调用。这种问题的思路是由上到下,再由下向上。通常是将一个复杂的问题逐层的分解成小问题,等到无法再分则返回,再将小问题拼装,然后逐层向上,返回大问题作为问题的解。通常在使用分治的思想时会使用有返回值的深度递归函数,这个应用在树中非常普遍。
以下为有返回值的递归函数的模板:
TYPE DFS_with_return(int idx){
// DFS terminate condition
// Normally there are two major categories
// One is for some number, already reach this depth according to the question, stop
// get to the end of an array, stop
if(idx == n || idx == (vector/string).size()){
return //"";
}
// very seldom only when our program met some efficiency problem
// do prune to reduce the workload
// no need do DFS if we already get the value of current element, just return
if(hash_table[input] != hash_table.end()){
return hash_table[input];
}
TYPE ans;
for(int i = ; i < n; i++){
if(visited[i] == ){
// normally, here should to add/concatenate the value in current level with the value returned from lower level
ans += DFS_no_return(idx + );
}
}
// if we need prune
// keep current value here
hash_table[input] = ans;
return ans;
}
总结:
- 递归函数的整体构造:
- 递归函数的分类:
- 无返回值:适用于求所有可能的解。
- 是一种由上而下,将大问题分解,在每一层提取出需要处理的小问题,然后向下递归,遇到递归终止的条件时,就得到一个问题的解,此时返回。
- 有返回值:使用与求个数/数量的问题。
- 是一种从上向下,将大问题分解到无法再分,然后再将分解后的小问题返回,逐层进行加工处理,然后再返回给上一层调用。
- 无返回值:适用于求所有可能的解。
DFS template and summary的更多相关文章
- Binary Search Tree DFS Template
Two methods: 1. Traverse 2. Divide & Conquer // Traverse: usually do not have return value publi ...
- C#设计模式系列:模板方法模式(Template Method)
你去银行取款的时候,银行会给你一张取款单,这张取款单就是一个模板,它把公共的内容提取到模板中,只留下部分让用户来填写.在软件系统中,将多个类的共有内容提取到一个模板中的思想便是模板方法模式的思想. 模 ...
- 设计模式系列13:模板方法模式(Template Method Pattern)
定义 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. --<设计模式GoF> UML类图 使用场景 有 ...
- 【DP】【CF31E】 TV Game
传送门 Description 给你一个长度为\(2n\)的数字,每次可以从左侧选一个数字,加入连接到一个数字\(A\)或另一个数字\(B\)后面.\(A,B\)初始为\(0\).\(A\)与\(B\ ...
- t4 加载文件到解决方案
Use EnvDTE add/remove multiple files to project By admin | décembre 17, 2013 Un commentaire Project ...
- winrt 上的翻书特效组件 源码分享 转载请说明
http://blog.csdn.net/wangrenzhu2011/article/details/10207413 (转) [TemplatePart(Name = A_PARTNAME, Ty ...
- Jmeter html 报告中添加90% line time
转载南风_real博客园:http://www.cnblogs.com/jaychang/p/5784882.html 首先上效果图: 其次明白几个原理: 90% Line的意思是:一组数由小到大进行 ...
- C# 使用C/S模式操作小票机打印
此方式适用于市场上大多数的小票机 佳博.POS58 等,不适用于有些标签打印机 比如斑马打印机等 直接贴代码: private FileStream fs = null; [DllImport(&qu ...
- 【JMeter】ant+jmeter生成html报告
源博文来自于 http://my.oschina.net/hellotest/blog/517518 主要应用于接口的回归或者性能的简单查看功能.操作为先在jmeter中写好测试计划,保存为jmx文 ...
随机推荐
- 1-最全CSS3选择器
一,CSS3 选择器分类 二,选择器语法 1,基本选择器语法 选择器 类型 功能描述 * 通配选择器 选择文档中所以HTML元素 E 元素选择器 选择指定类型的HTML元素 #id ID选择器 ...
- 转-MySQL for Mac 安装和基本操作
一.安装mysql 1.mysql下载地址:http://dev.mysql.com/downloads/mysql/ 2.安装软件包位于硬盘映象(.dmg)文件中,必须首先双击搜索起中的图标来安装该 ...
- 018 [工具软件]截图贴图注释 Snipaste
Snipaste 是一个截图贴图工具,绿色免费.官方主页:https://zh.snipaste.com/. 三大功能: 1.截图,可以自动识别窗口的各元素,可以精准到像素调整截图区域大小. 2.贴图 ...
- String的用法——判断功能
package cn.itcast_03; /* String的判断功能: 1.boolean equals(Object obj):字符串的内容是否相同,区分大小写 2.boolean equals ...
- Java数据类型和MySql数据类型对应一览 [转]
类型名称 显示长度 数据库类型 JAVA类型 JDBC类型索引(int) 描述 VARCHAR L+N VARCHAR java.lang.String 12 CHAR N ...
- Spark学习之Spark Streaming(9)
Spark学习之Spark Streaming(9) 1. Spark Streaming允许用户使用一套和批处理非常接近的API来编写流式计算应用,这就可以大量重用批处理应用的技术甚至代码. 2. ...
- java内存查看与分析
业界有很多强大的java profile的工具,比如Jporfiler,yourkit,这些收费的东西我就不想说了,想说的是,其实java自己就提供了很多内存监控的小工具,下面列举的工具只是一小部分, ...
- 关于Farseer.net轻量级ORM开源框架 V1.0 概念版本开发的消息
V0.2版的开源距离今天(05年03月)已有近3年的时间.可以说这个版本已经有点落伍的感觉了,呵呵. V0.2版至今一直处于BUG的修复及一些细小功能的增加,所以版本号上一直没有变化. 其实在这1.2 ...
- iOS截取特定的字符串(正则匹配)
有时候我们会有需求从一个字符串中截取其他的字符串,根据情况的不同,我们来分析几种方法~~ 一. 固定长度字符串中截取固定位置长度的字符串 // 这是比较简单的一种情况:比如截取手机号的后4位 let ...
- CREATE TABLE - 定义一个新表
SYNOPSIS CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name ( { column_name data_ty ...