回溯 算法

1: 回溯算法常用模版

// 主函数
main(
{
    // 1: 定义返回的结果集合res

    // 2: 定义回溯所需的组合combination,索引index

    // 3: 调用回溯函数
    backtrack(XXXX);

    // 4: 结束 return

}

// 回溯函数
void backtrack(res, combination, index)
{
    // 递归结束条件
    if (满足题目要求的目标) {
        res.push_back(combination)
        return;
    }

    // 临时变量
    new_idx = index;
    new_combination = combination;
    for (选择列表) { // 或者if
        // 1: 做选择
        //按需更新当前组合 new_combination

        // 2:递归回溯
        backtrack(res, new_commbination, new_index);

        // 3: 撤销选择
        // 恢复当前组合new_combination = combination
    }


    // 上述可能使用for遍历选择列表 或者使用 if更新
}

2: 回溯算法剪枝
由于回溯算法是枚举所有满足题意的组合,在递归的过程中如果不进行剪枝处理,就会出现重复的、多余的的组合。因此我们需要通过合理的剪枝处理来进行筛选
常见的剪枝方法:
(1) 选择列表进行剪枝
backtrack(para1, para2, start, ...) {
    for(int i = start; i < size; i++) { // 从start开始

        backtrack(para1, para2, i(或者i+1), …); // 下一次递归从自己所在i开始,不再回头看。 (若为i+1 表示不再选择自己)
    }//
    
}


(2) sort排序,之后去重
sort(candidates.begin(), candidates.end());
在backtrack之中
for (int i = start; i < candidates.size(); i++) {
    if ((i >= start + 1) && candidates[i] == candidates[i - 1])
        continue;

}

(3) view数组,标记搜索过的元素为true
vector<bool> view(nums.size(), false);// 这里的nums为原始的选择列表,view数组大小一致,初始为false
for(int i = 0; i < nums.size(); i++) {
    if (view[i] == true) continue;
    view[i] = true; // 标记,索引i的元素选择了
    // backtrack
    view[i] = false; // 撤销标记
}

(4) if return 结束没有必要的递归​​​​​​​


组合总和
https://leetcode.cn/problems/combination-sum/
https://leetcode.cn/problems/combination-sum-ii/submissions/

括号生存
https://leetcode.cn/problems/generate-parentheses/

电话号码的字母组合
https://leetcode.cn/problems/letter-combinations-of-a-phone-number/

全排列
https://leetcode.cn/problems/permutations/

组合
https://leetcode.cn/problems/combinations/

子集

https://leetcode.cn/problems/subsets/

子集II

https://leetcode.cn/problems/subsets-ii/​​​​​​​

复原IP地址

https://leetcode.cn/problems/restore-ip-addresses/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值