dfs求组合数题型


dfs求组合数

这种题型套路比较固定,应该是比较好总结的,但是我自从昨天刚刚接触,我人已经麻了。

感觉对dfs的机理,以及何时开始调用,内部的执行顺序不会知道的非常透彻。

误打误撞了ac了leetcode的几道题,今天先mark一下。之后写的题目多了之后,我继续再总结。

—————————————————————-10.27—————————————————————

组合

77. 组合 - 力扣(LeetCode) (leetcode-cn.com)

题目非常简洁,只有两个参数,n与k。给一个1到n的范围,每一个组合有k个数,列举出所有的可能。

class Solution {
public:
    vector path ; 
    vector> res ; 
    
    vector> combine(int n, int k) {
        dfs(1 , 0 , n , k) ; 
        return res ; 
    }
    
    
    void dfs(int start , int u , int n , int k)
    {
        if(u == k)
        {
            res.push_back(path) ; 
            return  ; 
        }
        
        for(int i = start ; i <= n  ; ++ i)
        {
            path.push_back(i) ; 
            dfs(i+1 , u +1 , n , k) ;
            path.pop_back() ; 
        }
    }
    return  ; 
};

组合总和

39. 组合总和 - 力扣(LeetCode) (leetcode-cn.com)

y总的思路,u的含义是遍历candidate数组的每一个下标。对每一个下标而言,用一个循环判断需要使用多少个该元素,对于每一轮改变target的值,恢复现场即可。

贴个代码:

class Solution {
public:
    vector ans ; 
    vector> res ; 
    
    
    vector> combinationSum(vector& candidates, int target) {
        dfs(0 , candidates , target) ; 
        return res ; 
    }
    
    void dfs(int u , vector candidates , int target)
    {
        if(target == 0)
        {
            res.push_back(ans) ; 
            return  ;
        }
        
        if(u == candidates.size())
        {
            return  ; 
        }
        
        for(int i = 0 ; i * candidates[u] <= target ; ++ i)
        {
            dfs(u + 1 , candidates , target - i * candidates[u]) ; 
            ans.push_back(candidates[u]) ; 
        }
        
        for(int i = 0 ; i * candidates[u] <= target ; ++ i)
        {
            ans.pop_back() ; 
        }
     return ;    
    }
};

组合总和II

40. 组合总和 II - 力扣(LeetCode) (leetcode-cn.com)

与上面一题的区别是,数组中有了重复元素,但是只能用已有的元素,就是将个数限定死了,不是想上面一题类似于完全背包问题。

我们只需要在找数量的时候,加一条限制,不超过所给的数量即可。但是有一点要注意,要进行去重,否则答案会出现很多重复答案。

贴个代码:

class Solution {
public:
    vector ans ;
    vector> res ;
    unordered_map ha ; 
    
    vector> combinationSum2(vector& candidates, int target) {
        sort(candidates.begin() , candidates.end()) ; 
        for(int num : candidates)
        {
            ha[num] ++ ; 
        }
        candidates.erase(unique(candidates.begin() , candidates.end()) , candidates.end()) ; 
        dfs(0 , candidates , target) ;
        return res ; 
    }
    
    void dfs(int u , vector candidates ,int target)
    {
        if(target == 0)
        {
            res.push_back(ans) ; 
            return  ; 
        }
        
        if(u == candidates.size())
        {
            return ; 
        }
        
        for(int i = 0 ; i * candidates[u] <= target && i <= ha[candidates[u]] ; ++ i)
        {
            dfs(u+1 , candidates , target - i * candidates[u]) ; 
            ans.push_back(candidates[u]) ;         
        }
        for(int i = 0 ; i * candidates[u] <= target && i <= ha[candidates[u]] ; ++ i)        
        {
            ans.pop_back() ; 
        }
        return ; 
    }
};

组合总和III

216. 组合总和 III - 力扣(LeetCode) (leetcode-cn.com)

class Solution {
public:
    vector ans ;
    vector> res ; 
    
    
    vector> combinationSum3(int k, int n) {
        dfs(1 , 0 , k , n) ;
        return res ; 
    }
    
    void dfs(int start , int u , int k , int n)
    {
        if(u == k)
        {
            int num = accumulate(ans.begin() , ans.end() , 0) ; 
            if(num == n)
            {
                res.push_back(ans) ; 
                return  ; 
            }
        }
           for(int i = start ; i <= 9; ++ i)
        {
            if(i > n)
                return  ; 
            ans.push_back(i) ; 
            dfs(i + 1 , u + 1 , k , n ) ; 
            ans.pop_back() ; 
        }
        return ; 
    }
};

ok,今天就mark到这,我人已经麻了………


文章作者: 罗林
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 罗林 !
  目录