C++回溯算法之一

本文详细介绍了C++中如何实现回溯算法,通过实例解析了回溯法在解决组合优化问题中的应用,包括八皇后问题、数独求解等经典案例。深入理解回溯算法的原理和步骤,助你提升编程解题能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

输入:"abbaca"
输出:"ca"
解释:例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
*/


#include <iostream>
#include<string>
#include<algorithm>

using namespace std; 

int main()

{
   
    string str = "abbaca";
    string result;
    for (char s : str)
    {
   
        if (result.empty()||result.back()!=s)
        {
   
            result.push_back(s);
        }
        else
        {
   
            result.pop_back();
        }
    }
  
    cout << result;

}
/*
给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。

示例:

输入: n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

*/


#include <iostream>
#include<string>
#include<algorithm>
#include<vector>
//#include<map>
//#include<set>
//#include<unordered_set>
#include<stack>

using namespace std; 
class Solution {
   
private:
    vector<vector<int>> result; // 存放符合条件结果的集合
    vector<int> path; // 用来存放符合条件结果
   
    void backtracking(int n, int k, int startIndex=1)
    {
   
        if (path.size() == k)
        {
             
            result.push_back(path);
            return;
        }
         for (int i = startIndex; i <= n; i++) 
        {
   
            path.push_back(i);              // 处理节点 
            backtracking(n, k, i + 1);<
### C++回溯算法的实现与解释 #### 示例代码 以下是基于引用内容提供的一个完整的 C++ 回溯算法示例,该示例解决了从 `n` 个同整数中选取长度为 `k` 的所有组合的问题。 ```cpp #include <iostream> #include <vector> using namespace std; class Solution { public: vector<vector<int>> res; vector<int> path; // 回溯函数定义 void backtrack(int n, int k, int start) { if (path.size() == k) { // 当前路径满足条件时保存结果 res.push_back(path); return; } for (int i = start; i <= n; ++i) { // 枚举当前可选的元素 path.push_back(i); // 尝试选择当前元素 backtrack(n, k, i + 1); // 进入下一层递归 path.pop_back(); // 撤销选择,回到上一状态 } } // 主调用接口 vector<vector<int>> combine(int n, int k) { backtrack(n, k, 1); // 初始状态从第一个元素开始枚举 return res; } }; // 测试代码 int main() { Solution sol; int n = 4, k = 2; vector<vector<int>> result = sol.combine(n, k); cout << "Combinations of size " << k << " from numbers 1 to " << n << ":" << endl; for (const auto& comb : result) { for (int num : comb) { cout << num << " "; } cout << endl; } return 0; } ``` --- #### 代码解析 1. **类成员变量初始化** - 使用个向量 `res` 和 `path` 来分别存储最终的结果集合以及当前正在构建的部分解。 - `res`: 存储所有的有效组合。 - `path`: 记录当前递归层所形成的部分解。[^3] 2. **核心逻辑:回溯函数 (`backtrack`)** - 参数说明: - `n`: 总共可用的数字范围 `[1, n]`。 - `k`: 组合的目标大小。 - `start`: 当前递归状态下允许选择的最小起始位置。 - 如果 `path` 的大小等于 `k`,则将当前部分解加入到结果集中并返回。这一步对应于剪枝操作的一部分,确保只保留符合条件的解。[^1] - 对于每一个可能的选择(由循环控制),将其加入到 `path` 并进入更深的一层递归;之后再撤销这一选择以便继续探索其他可能性。这是典型的深度优先搜索(DFS)方式的应用。[^4] 3. **入口方法 (`combine`)** - 初始化回溯过程,指定起点为 `1`,因为题目假设输入是从正整数序列 `[1, n]` 开始的。 4. **测试运行** - 设置参数 `n=4`, `k=2` 表明我们需要找出从 `{1, 2, 3, 4}` 中选出任意数的所有组合。 - 输出结果显示每种合法的组合形式。 --- #### 关键概念总结 - **约束条件**: 在此例子中表现为仅考虑固定大小 `k` 的子集作为解决方案之一。如果超出这个限制,则立即停止进一步扩展这条路径。 - **剪枝优化**: 减少必要的计算开销非常重要。例如,在上述程序里通过调整循环上限实现了简单的剪枝效果,避免了无效的状态转移。具体而言,对于剩余未处理项足以构成完整解的情况提前终止迭代。[^2] - **递归结构**: 整体流程依赖递归来模拟逐级深入的过程,直到触及边界条件为止。每次完成一次成功的匹配后都会退回到之前的状态重新试探新的选项。[^5] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值