回溯法 或dfs 或深度优先 题总结
来源:互联网 发布:嵌入式c语言 编辑:程序博客网 时间:2024/06/05 02:50
回溯法总结
一道数字到字符串的题,将数字映射到手机的字符串上,是编程之美版本的简略版,简明的DFS,其实我更愿意用backtrack framework来做,说成是回溯法,本质没有区别
期间犯了一个错误,就是for里面多写了一个f(),结果导致out of memory等奇怪错误。 主要是受了candidate有两个情况,直接写成两个,外加用select bool数组将unmake 和下一轮的make重合在一起,于是下意识的多写了一个f() 而没有仔细思考。
其实一般框架都是一个for里面先逐个make candidate,然后递归,然后unmake
外加一道子集和问题,返回给定集合S 的所有子集,典型的回溯。其实感觉这个就是有模板的,但是如果情况复杂些,我还是改起来有点费劲= =
打印 C(n,k)的所有情况,里面多一个k,于是对应多一个selectk表示当前已经选了多少变量了,好像递归出口如果写成下面这个会有问题,
具体还没分析出为啥= =
C(n,k)代码
总结:回溯法其实就是你for循环要做,但是不知道多少层for循环的时候,或者是解指数(子集树)或者阶乘级(排列树),然后里面涉及的每个当前解的变量要么数组传递,递归调用共享访问,要么vector引用传递保持递归调用一致,要么全局变量。
然后记录全局变量的也是如此,保持全局一致,如果作为递归参数千万不要值传递,导致每个递归栈保存的都是一个copy而不是访问全局的一个。然后递归出口的时候一定要把情况罗列清楚,多个条件逻辑与或分析能力。
一道数字到字符串的题,将数字映射到手机的字符串上,是编程之美版本的简略版,简明的DFS,其实我更愿意用backtrack framework来做,说成是回溯法,本质没有区别
vector<string> numtoletter;void f(vector<char>& strvec, int selectn, int n,string digits, vector<string> numtoletter, vector<string>& allcombinations){if(selectn==n){string str;for(int i=0;i<n;i++)str+=strvec.at(i);allcombinations.push_back(str);}else{for(int i=0;i< numtoletter.at(digits.at(selectn)-'2').length();i++)// if 1?{strvec.push_back(numtoletter.at(digits.at(selectn)-'2').at(i));f(strvec,selectn+1,n,digits,numtoletter,allcombinations);strvec.pop_back();//f(strvec,selectn+1,n,digits,numtoletter,allcombinations);}}}vector<string> letterCombinations(string digits) {numtoletter.push_back("abc");numtoletter.push_back("def");numtoletter.push_back("ghi");numtoletter.push_back("jkl");numtoletter.push_back("mno");numtoletter.push_back("pqrs");numtoletter.push_back("tuv");numtoletter.push_back("wxyz");vector<char> strvec;vector<string> allcombinations;f(strvec,0,digits.size(),digits,numtoletter,allcombinations);return allcombinations;}
期间犯了一个错误,就是for里面多写了一个f(),结果导致out of memory等奇怪错误。 主要是受了candidate有两个情况,直接写成两个,外加用select bool数组将unmake 和下一轮的make重合在一起,于是下意识的多写了一个f() 而没有仔细思考。
其实一般框架都是一个for里面先逐个make candidate,然后递归,然后unmake
外加一道子集和问题,返回给定集合S 的所有子集,典型的回溯。其实感觉这个就是有模板的,但是如果情况复杂些,我还是改起来有点费劲= =
void subsets_recur(bool *select, vector<int> S, vector<vector<int>>&intvec, int selectn, int n){if(selectn==n){vector<int> vec;for(int i=0;i<S.size();i++){if(select[i]==true)vec.push_back(S.at(i));}intvec.push_back(vec);}else{select[selectn]=false;//not selectsubsets_recur(select,S,intvec,selectn+1,n);select[selectn]=true;subsets_recur(select,S,intvec,selectn+1,n);}}vector<vector<int> > subsets(vector<int> &S) {bool *select=new bool[S.size()];vector<vector<int>> intvec;sort(S.begin(),S.end());subsets_recur(select,S,intvec,0,S.size());delete[] select;return intvec;}
打印 C(n,k)的所有情况,里面多一个k,于是对应多一个selectk表示当前已经选了多少变量了,好像递归出口如果写成下面这个会有问题,
具体还没分析出为啥= =
if(selectk==k){string str;for(int i=0;i<n;i++)if(select[i]==true)str+='1';elsestr+='0';//cout<<endl;numset.push_back(str);}else if(selectn==n);else{select[selectn]=false;SubSetNum(numset,select,selectk,k,selectn+1,n);select[selectn]=true;SubSetNum(numset,select,selectk+1,k,selectn+1,n);}
C(n,k)代码
void Combinations(bool* select, vector<vector<int>> &vecset,int selectk, int k, int selectn, int n){if(k>n) return ;if(selectn==n){if(selectk==k)//proning{vector<int> vec;for(int i=0;i<n;i++){if(select[i]==true)vec.push_back(i+1);}vecset.push_back(vec);}}else{select[selectn]=false;Combinations(select, vecset,selectk,k,selectn+1,n);select[selectn]=true;Combinations(select, vecset,selectk+1,k,selectn+1,n);}}vector<vector<int> > combine(int n, int k){bool* select=new bool[n];memset(select,0,sizeof(bool)*n);vector<vector<int>> vecset;Combinations(select,vecset,0,k,0,n);delete [] select;return vecset;}
总结:回溯法其实就是你for循环要做,但是不知道多少层for循环的时候,或者是解指数(子集树)或者阶乘级(排列树),然后里面涉及的每个当前解的变量要么数组传递,递归调用共享访问,要么vector引用传递保持递归调用一致,要么全局变量。
然后记录全局变量的也是如此,保持全局一致,如果作为递归参数千万不要值传递,导致每个递归栈保存的都是一个copy而不是访问全局的一个。然后递归出口的时候一定要把情况罗列清楚,多个条件逻辑与或分析能力。
本质是for遍历每个数,make, recursive, unmake 不要多加recursive导致和 01选择的混淆
但是如果弄个有重复数字的全排列,我就搞不清了,还有重复数字的组合数= =
0 0
- 回溯法 或dfs 或深度优先 题总结
- POJ 1321 棋盘问题(DFS深度优先搜索/回溯法)
- POJ 1321 棋盘问题(DFS深度优先搜索/回溯法)
- BFS广度优先搜索 DFS深度优先搜索 回溯算法
- DFS深度优先搜索总结
- 回溯法--深度优先搜索
- 回溯法,深度优先遍历
- poj 3050(dfs+回溯或bfs均可)
- HDU1584(dfs回溯 或 区间dp)
- 用深度优先搜索(DFS)(回溯法)解决N皇后问题(Leetcode 51)
- leetcode 282. Expression Add Operators 深度优先遍历DFS + 回溯
- 深度优先搜索算法(DFS) 总结
- 深度优先+回溯法生成随机迷宫
- 回溯法实例-深度优先搜索
- 深度优先搜索 DFS
- 深度优先搜索 DFS
- 深度优先遍历DFS
- DFS 深度优先搜索
- C#访问MySQL数据库的方法
- IOS开发缓存机制之—内存缓存机制
- 形态学滤波算法
- Swift——(五)Swift中的那些默认值
- jvm-加载器-学习笔记(1)
- 回溯法 或dfs 或深度优先 题总结
- 数据结构快速回顾——二叉查找树
- UVa 392 - Polynomial Showdown
- 说:在结果里换行后追加要说的内容 20140623
- 画一条直线
- Struts2上传图片文件失败
- swift 3. 基本数据类型
- C# UDP编程简介
- 前端学习——使用Ajax方式POST JSON数据包