DFS求组合的问题~
来源:互联网 发布:淘宝话费券怎么用 编辑:程序博客网 时间:2024/06/05 18:40
leetcode上面有很多类似的变形问题~这类问题的求解非常相似,一般用DFS递归求解~下面总结一下:
我们从全排列C(M,N)开始
1、
Combinations
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
For example,
If n = 4 and k = 2, a solution is:
[ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4],]
明显用DFS解决,在(1-n)中一直递归选择下一个数 直到不能进行为止,当我们选择一个排列后,即size()==k,本次return,去掉上次选择的数,继续向下递归,(譬如我们刚开始选择12,size=2,去掉2,再从(3-4)中间选择,一直到不能继续为止),跟深度优先遍历树思路一致。C++代码如下:
void dfsCNKUique(vector<vector<int> > &v, vector<int> &mv, int n, int k, int start) { if (mv.size() == k) { v.push_back(mv); return; } for (int i = start; i <= n; i++) { mv.push_back(i); dfsCNKUique(v, mv, n, k, i+1); mv.pop_back(); } }
如果我们求A(m,n)该怎么求呢? 其实非常简单,只要修改一个变量即可
void dfsANKUique(vector<vector<int> > &v, vector<int> &mv, int n, int k, int start) { if (mv.size() == k) { v.push_back(mv); return; } for (int i = start; i <= n; i++) { mv.push_back(i); dfsANKUique(v, mv, n, k, start+1); mv.pop_back(); } }
再修改一个需求,我们要得到如下的结果:如果输入n=4,k=2;结果如下:[4,4], [3,4], [3,3], [2,4], [2,2], [2,3], [1,1], [1,2], [1,3], [1,4],代码如下:void dfsCNKNotUique(vector<vector<int> > &v, vector<int> &mv, int n, int k, int start) { if (mv.size() == k) { v.push_back(mv); return; } for (int i = start; i <= n; i++) { mv.push_back(i); dfsCNKUique(v, mv, n, k, i); mv.pop_back(); } }同理,如果变形A(m,n)数可以重复,只需要将start+1变位start即可(此种情况会出现两个完全相同数重复的现象)。下面来看一道变形的求和的组合的问题2、Combination Sum
Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:
- All numbers (including target) will be positive integers.
- Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
- The solution set must not contain duplicate combinations.
For example, given candidate set 2,3,6,7
and target 7
,
A solution set is: [7]
[2, 2, 3]
分析了问题1之后,这道问题就不是个事了,不就是求全排列C(1,N)...C(#,N)么,看是否与target相等。当然我们要注意,相同的数字可以连加,但是要保证不能有相同的组合,另外,全排列的上界#如何确定,他并不是单纯的N这么简单,假设numbers C中有一个数字为1,T为1000,那么存在一个组合1....1相加为1000,因此,上界确定也就呼之欲出了,首先我们需要对numbers C按非降序排序,这样,上界就是n=T/C[0]。
C++代码如下:
void dfsSumCombin(vector<vector<int> >& ret, vector<int>& vec, vector<int> &candidates, int target, int n, int sum,int cur) {if(sum > target)return;if(vec.size() == n) {if(sum == target) {ret.push_back(vec);}}for(int i = cur; i < candidates.size(); i++) {vec.push_back(candidates.at(i));dfsSumCombin(ret,vec,candidates,target,n,sum+candidates.at(i),i);vec.pop_back();}}
vector<vector<int> > combinationSum(vector<int> &candidates, int target) {vector<vector<int> > ret;int m = candidates.size();if(0==m)return ret;vector<int> vec;int n = target/candidates.at(0);for(int i = 1; i <= n; i++) {dfsSumCombin(ret,vec,candidates,target,i,0,0);}return ret;}
再看一道变形题,A了挺久的,囧~~~~~~~~~
3、Letter Combinations of a Phone Number
Given a digit string, return all possible letter combinations that the number could represent.
A mapping of digit to letters (just like on the telephone buttons) is given below.
Input:Digit string "23"Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].Note:
题目意思很简单,跟上面几道题思路差不多,但是很多细节要注意,如果对递归了解不深的话,很难一遍AC。
Although the above answer is in lexicographical order, your answer could be in any order you want.
刚好趁这道题熟悉了一下map的用法,递归代码简单易懂。但是卡了蛮久的,修为还是太浅。而且好几次bug,代码有点长,主要是用了map,并借助了一个两个vector程序显得不太简洁,如下代码:
void dfs(vector<string>& vec,vector<string>& ret,string& s,int n, int cur) { if(s.size() == n) { vec.push_back(s); return; } for(int i = 0; cur < ret.size() && i <ret.at(cur).size(); i++){//这里循环的是第cur个string里面的每个char,i由0开始 string temp = s; temp+=ret.at(cur).at(i); dfs(vec,ret,temp,n,cur+1); } } vector<string> letterCombinations(string digits) { vector<string> vec; int n = digits.size(); map<char,string> mapdict; initMaps(mapdict);//初始化map对象 vector<string> ret; findAdaptMap(ret,mapdict,digits);//找到每个按下的数字键对应的string string s; dfs(vec,ret,s,n,0); return vec; } void findAdaptMap(vector<string>& ret, map<char,string>& mapdict, string digits) { int n = digits.size(); for(int i = 0; i < n; i++) { char s = digits.at(i); ret.push_back(mapdict[s]); } } void initMaps(map<char,string>& mapdict) { mapdict.insert(map<char,string>::value_type('2',"abc")); mapdict.insert(map<char,string>::value_type('3',"def")); mapdict.insert(map<char,string>::value_type('4',"ghi")); mapdict.insert(map<char,string>::value_type('5',"jkl")); mapdict.insert(map<char,string>::value_type('6',"mno")); mapdict.insert(map<char,string>::value_type('7',"pqrs")); mapdict.insert(map<char,string>::value_type('8',"tuv")); mapdict.insert(map<char,string>::value_type('9',"wxyz")); }
- DFS求组合的问题~
- DFS-intcode求组合
- DFS经典组合问题
- 三个数求加法组合的问题
- 求集合的组合和排列问题
- DFS求迷宫问题
- 求组合数问题
- hdu 1799 DFS求组合数
- DFS暴力求某集合上的某种的组合情况
- nyoj+求所有组合数,dfs,递归需要好好理解
- 求字符串的所有组合
- 求字符串的所有组合
- 求字符串的所有组合
- 求字符的所有组合!
- 求元素组合的算法
- poj 1111 dfs求面积问题
- 关于求所有五阶幻方组合数问题
- 求C(n,m)组合问题
- adb shell input command
- Bluedroid From A2DP|source code reading note
- hibernate4.3入门教程,使用maven配置
- Prime Ring Problem DFS
- 结构体枚举的小结
- DFS求组合的问题~
- char*及char[]申请内存空间区别
- js xss系列防御转载文章(4)
- Git客户端变量设置
- cydiasubstrate
- 读写文本文件
- c++ vector
- equals == 区别和Object类
- Oracle11g_adg+fast failover+dg_broker