回溯算法-组合问题

**回溯搜索法-**纯暴力搜索,不是一种高效的算法。但因为有些问题能够通过回溯法解决已经很棒了,回溯法比那种通过多层循环的效率还是要高很多的。

回溯法均可抽象为一个N叉树形结构,这个树的宽度是这个集合所有的元素,深度为递归的深度。如下图:
在这里插入图片描述
回溯三步曲
1.递归函数参数和返回值
2.确定终止条件
3.单层递归逻辑

回溯法模板
void backtracking(参数值)//回溯法参数不容易确定,一般先写逻辑,需要什么参数,就写什么参数。
{
if(终止条件)://有递归就一定有终止条件
收集结果;
return;
for(集合元素)
{
处理节点;
递归过程;//树形结构往下分叉
回溯过程;//即撤销操作,递归后面往往是回溯
}
}

回溯法解决问题类型
(1)组合类问题
力扣77题
1.参数与返回值的确定
二维数组 result
一维数组 path
void backtracking(n,k,start_index)
{
}
2.终止条件的确定
if(path.size()==k):
{
result.push(path);
return;
}
3.单层逻辑问题
for (i=start_index;i<=n;i++)
{
path.push(i)
backtracking(n,k,i+1);//递归
path.pop()//回溯
}
回溯常常伴随着剪枝操作,剪枝操作指的是对于一些不可能满足要求的子孩子,则不需要对其进行递归操作,直接在单层逻辑问题上就可以对其进行剪枝操作。
这一题的剪枝操作可以如下:
假设有n个数,需要寻找k个数的集合,而此时的path中数目为path.size,因此i至多从(n-(k-path.size)+1)处选取。这个值的得到是根据假设这个至多值为m,这个m到n后面的所有值的大小是等于(n-m+1)=(k-path.size)
因此可以推得m=n-(k-path.size)+1。即代码修改为
for (i=start_index;i<=n-(k-path.size)+1;i++)
{
path.push(i)
backtracking(n,k,i+1);//递归
path.pop()//回溯
}

(2)切割问题
例:字符串切割问题:寻找回文子串
(3)子集问题
(4)排列问题
(5)棋盘问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值