递归的深度讲解(dfs)

递归

递归就是自己调用自己的过程(虽然这就话在很多博客上都这么说,但我还是要说一遍)。
但是在学习递归的过程中,千万不要像上面这么理解(ಡωಡ)
因为你会像套娃一样的套个不停(强迫症(ಡωಡ))
思路一:
所以你要把内部的递归理解为调用其他的函数,例如:

void dfs(int index){
	dfs(index-1);//这里的dfs可以理解为:调用名字字一样的另一个函数
}

保持这个思路继续往下:
思路二:
在递归的过程中只要考虑特殊的状态就ok了。其实特殊的状态只有两个,那就是
1.中心
2.边界

中心可以理解为一般的情况
边界可以理解为特殊的情况

以下的教程都基于这两个思路来进行
我们通过举几个例子讲解一下:
1.全排列
将1-9这九个数字进行位数为3的全排列
就像这样子123、199、927
直接上代码(ಡωಡ)

dfs函数是这样

void dfs(int range,int index,string str){//index代表当数字范围,maxn代表当前搜索到第多少列
	if (index == 0){
		cout << str << endl;
	}
	else{
		for (int i = 1; i <= range; i++){
			str += i + '0';
			dfs(range, index-1, str);
			str.pop_back();
		}
	}
}

主函数是这样

int main(){

	dfs(9, 3,"");//1-7的三位数字的全排列

	return 0;
}

整体思路:
通过增减字符串来达到保存一次匹配成功的状态
这个例子是通过遍历数字的每一位位数遍历从后往前,到0时停止
看到这里可能会感觉 (看)(求)(不)(懂),接下来进入正题。
再把上面的代码copy一遍(防丢)

void dfs(int range,int index,string str){//index代表当数字范围,maxn代表当前搜索到第多少列
	if (index == 0){
		cout << str << endl;
	}
	else{
		for (int i = 1; i <= range; i++){
			str += i + '0';
			dfs(range, index-1, str);
			str.pop_back();
		}
	}
}

依据思路二:
这里的中心是指:

	else{//对于中心来说(相当于数字的每一位)都有9种可能,for循环就是这么来的
		for (int i = 1; i <= range; i++){
			str += i + '0';//增加字符串
			dfs(range, index-1, str);//位数直接自键,与边界相对应
			str.pop_back();//再遍历完每一种可能之后要记得将增加的删除掉,用来进行下一次的dfs
		}
	}

这里的边界是指:

if (index == 0){//如果到达边界,直接把str输出
		cout << str << endl;
	}

讲完了(ಡωಡ)
(ಡωಡ)
接下来讲组合

#include<iostream>
#include<string>
using namespace std;

int book[100];

void dfs(int range,int index,string str){
	if (index == 0){
		cout << str << endl;
	}
	else{
		for (int i = 1; i <= range; i++){
			if (!book[i]){
				book[i] = 1;
				str += i + '0';
				dfs(range, index - 1, str);
				str.pop_back();
				book[i] = 0;
			}
			
		}
	}
}

int main(){

	dfs(9, 3,"");

	return 0;
}

看完之后是不是觉得和排列大同小异(ಡωಡ),其实只多了一个book数组,用来记录这个数字每一位的使用情况,如果是1,表示使用过,如果是0,就是没使用相当于去掉排列重复的部分

如果你看懂这些之后还有一些技巧
以后补充(ಡωಡ)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值