DFS-leetcode Combination Sum I/I I
深度优先搜索(DFS)它是一个搜索算法。第一次接触DFS它应该是一个二进制树的遍历内部,二叉树预订、序和后序实际上属于深度遍历-first。在本质上,深度优先搜索,遍历中则看到了更纯正的深度优先搜索算法。
通常。我们将回溯法和DFS等同看待。能够用一个等式表示它们的关系:回溯法=DFS+剪枝。所以回溯法是DFS的延伸。其目的在于通过剪枝使得在深度优先搜索过程中假设满足了回溯条件不必找到叶子节点。就截断这一条路径,从而加速DFS。
实际上,即使没有剪枝,DFS在从下层回退到上层的时候也是一个回溯的过程,通常这个时候某些变量的状态。
DFS通经常使用递归的形式实现比較直观。也能够用非递归。但通常须要借组辅助的数据结构(比方栈)来存储搜索路径。
以下通过leetcode上的两个题目,来展示DFS的应用:
题一 Combination Sum I,题目大意是这种:有一个正整数集合C,和一个目标数T(T也为正整数)。现从C中选出一些数,使其累加和恰好等于T(C中的每一个数都能够取若干次),求全部不同的取数方案。
比如:C={2,3,6,7} T=7
res={ [7],
[2, 2, 3] }
- class Solution {
- public:
- vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
- vector<int> tmp;
- sort(candidates.begin(),candidates.end()); //先对C中候选数升序排序。为后面的剪枝做准备
- sou=candidates;
- dfs(tmp,target,0);
- return res;
- }
- private:
- vector<vector<int> > res; //保存最后结果
- vector<int> sou;
- int sum(vector<int> tmp){ //计算累加和
- int r=0;
- for(int i=0;i!=tmp.size();++i)
- r+=tmp[i];
- return r;
- }
- void dfs(vector<int> &tmp,int tag,int l){
- if(l==sou.size()) //搜索到叶节点
- return ;
- int tot=sum(tmp);
- if(tot==tag){
- res.push_back(tmp);
- return ;
- }else if(tot>tag) //剪枝
- return ;
- else{
- for(int i=l;i!=sou.size();++i){ //由于C中每一个数能够选多次,所以i从l開始,而不是l+1
- tmp.push_back(sou[i]);
- dfs(tmp,tag,i);
- tmp.pop_back(); //回溯,恢复tmp状态
- }
- }
- }
- };
题二 Combination Sum II,与题一得差别是集合C中的每一个数最多仅仅能取一次,只是C中能够有反复的数。
比如:C={10,1,2,7,6,1,5} T=8
res={ [1, 7]
[1, 2, 5]
[2, 6]
[1, 1, 6] }
题二能够採用与题一类似的方法。可是因为题二中的每一个数仅仅能取一次,所以dfs函数中的for循环,i应从l+1開始,表示取下一个数。但这样带来的问题是,结果中会出现反复的取数方案。拿上面的样例来分析:C中有两个1能够选,那第一个1和7是一种可选方案(1+7=8)。第二个1和7也是一种可选方案,依照上述算法。[1,7]会在结果中出现两次。当然能够对最后结果去重(假设用C++的话,sort->unique->erase能够实现)。
不幸的是,这样的解法会超时。解决超时的方案是不要将反复的方案增加到结果集中。也就避免了去重的工作。AC代码例如以下:
- class Solution {
- public:
- vector<vector<int> > combinationSum2(vector<int> &candidates, int target) {
- vector<int> tmp;
- for(int i=0;i!=candidates.size();++i){ //mm是一个map,key为C中可取的数,value为该数有多少个
- mm[candidates[i]]++;
- }
- for(map<int,int>::iterator it=mm.begin();it!=mm.end();++it){
- for(int i=0;i<it->second;++i){
- tmp.push_back(it->first);
- dfs(tmp,target,it);
- }
- for(int i=0;i<it->second;++i){ //回溯。恢复tmp状态
- tmp.pop_back();
- }
- }
- return res;
- }
- private:
- vector<vector<int> > res; //保存最后结果
- map<int ,int > mm;
- int sum(vector<int> tmp){ //计算累加和
- int r=0;
- for(int i=0;i!=tmp.size();++i)
- r+=tmp[i];
- return r;
- }
- void dfs(vector<int> &tmp,int tag,map<int,int>::iterator it){
- if(it==mm.end()) //搜索到叶节点
- return ;
- int tot=sum(tmp);
- if(tot==tag){
- res.push_back(tmp);
- return ;
- }else if(tot>tag) //剪枝
- return ;
- else{
- for(++it;it!=mm.end();++it){
- for(int i=0;i<it->second;++i){
- tmp.push_back(it->first);
- dfs(tmp,tag,it);
- }
- for(int i=0;i<it->second;++i){ //回溯,恢复tmp状态
- tmp.pop_back();
- }
- }
- }
- }
- };
关键代码:
- for(++it;it!=mm.end();++it){
- for(int i=0;i<it->second;++i){
- tmp.push_back(it->first);
- dfs(tmp,tag,it);
- }
- for(int i=0;i<it->second;++i){ //回溯,恢复tmp状态
- tmp.pop_back();
- }
- }
外层循环表示依次从C中选取一种数。内层的第一个循环表示C中这个数能够取几次,内层的第二个循环表示,假设不选上一个数的话。要恢复状态。即把保存的上一个数删除(增加了多少个,就删除多少个)。
版权声明:本文博客原创文章。博客,未经同意,不得转载。
DFS-leetcode Combination Sum I/I I的更多相关文章
- 回溯法和DFS leetcode Combination Sum
代码: 个人浅薄的认为DFS就是回溯法中的一种,一般想到用DFS我们脑中一般都有一颗解法树,然后去按照深度优先搜索去寻找解.而分支界限法则不算是回溯,无论其是采用队列形式的还是优先队列形式的分支界限法 ...
- [LeetCode]Combination Sum题解(DFS)
Combination Sum Given a set of candidate numbers (C) (without duplicates) and a target number (T), f ...
- LeetCode Combination Sum III
原题链接在这里:https://leetcode.com/problems/combination-sum-iii/ 题目: Find all possible combinations of k n ...
- LeetCode: Combination Sum I && II && III
Title: https://leetcode.com/problems/combination-sum/ Given a set of candidate numbers (C) and a tar ...
- LeetCode: Combination Sum 解题报告
Combination Sum Combination Sum Total Accepted: 25850 Total Submissions: 96391 My Submissions Questi ...
- [Leetcode] Combination Sum 系列
Combination Sum 系列题解 题目来源:https://leetcode.com/problems/combination-sum/description/ Description Giv ...
- [LeetCode] Combination Sum IV 组合之和之四
Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...
- [LeetCode] Combination Sum III 组合之和之三
Find all possible combinations of k numbers that add up to a number n, given that only numbers from ...
- [LeetCode] Combination Sum II 组合之和之二
Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in ...
- [LeetCode] Combination Sum 组合之和
Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C wher ...
随机推荐
- 小米2S 中文和英文支持TWRP,真实双系统支持
经过我几天的努力小米2S的TWRP 的功能已经完美了. 支持功能 : 中文和英文显示能相互切换 真实双系统功能已经完成95%. 刷入手机方法.由于时间原因我只制作了img文件.没有制作成卡刷包格式. ...
- 重新想象 Windows 8 Store Apps (20) - 动画: ThemeAnimation(主题动画)
原文:重新想象 Windows 8 Store Apps (20) - 动画: ThemeAnimation(主题动画) [源码下载] 重新想象 Windows 8 Store Apps (20) - ...
- poj1163The Triangle(简单DP)
转载请注明出处:viewmode=contents">http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://poj ...
- mapreduce程序来实现分类
文件的内容例如以下所看到的: 5 45 8 876 6 45 要求最后的输出格式: 1 5 2 6 3 8 4 45 5 45 5 876 首先,这个题目是须要对文 ...
- RH133读书笔记(2)-Lab 2 Working with packages
Lab 2 Working with packages Goal: To gain working experience with package management System Setup: A ...
- 采用Java语言如何实现高速文件复制?
今天review代码也看到了"大神"用老方法来实现文件拷贝.今天归结一下使用Java语言怎样实现高速文件复制: 代码1--使用文件通道的方式: import java.io.Fil ...
- 大哥可以写KMP该——达到strstr()
在最后采访,面试官要求实现strstr(),当场就蒙了. 这个题目是模式匹配问题.<算法导论>里列出了几种字符串匹配算法: 朴素算法 | Rabin-Karp | 有限自己主动机算法 | ...
- 安装framework 3.5出现0x800F0922的解决方法
关闭Windows 防火墙,启动Windows model install服务 重启! 再安装 就ok了
- Chapter 1 Securing Your Server and Network(4):使用虚拟服务帐号
原文:Chapter 1 Securing Your Server and Network(4):使用虚拟服务帐号 原文出处:http://blog.csdn.net/dba_huangzj/arti ...
- BestCoder Round #16
BestCoder Round #16 题目链接 这场挫掉了,3挂2,都是非常sb的错误 23333 QAQ A:每一个数字.左边个数乘上右边个数,就是能够组成的区间个数,然后乘的过程注意取模不然会爆 ...