微软面试题: LeetCode 39. 组合总和 出现次数:2
题目描述:
解析:
此类题目 回溯法 相关的题型:排列、组合、子集相关问题
回溯相关问题 可参考 :
https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liweiw/
解决此类问题需要注意以下几个方面:
1. 需不需要设置 visited 数组:当给定的 candidate 数组中元素不能重复使用时,在 dfs 前进时需要标记和回溯时需取消标记;
2. 需不需要设置 begin 下标: 当题目要求得到的结果 如[1,2,3] 、[2,3,1]、[3,1,2]只能在结果集中存在一个时使用begin 变量,去重并剪枝;
3. 需不需要对给定candidate 数组排序:看剪枝需要,如 本题中的 if(sum + candidate [i] > m_target) break; 就是一个要求排序的剪枝操作;
4. 需不需要跳重复: 当给定candidate 中有重复元素时,需先对 candidate 排序,然后跳重,如 if(i > 0 && candidate[i-1] == candidate[i] && visited[i-1] == 0) continue;
5.需不需要回溯操作:大部分都需要回溯,除非只需要得到一个结果,第一次遍历到对应的叶节点时,就停下,不需要回溯。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 class Solution { 4 public: 5 vector<vector<int>> combinationSum(vector<int>& candidates, int target) 6 { 7 m_target = target; 8 vector<vector<int>> res; 9 vector<int> path; 10 int sum = 0; 11 std::sort(candidates.begin(),candidates.end()); 12 dfs(0,res,path,sum,candidates); 13 return res; 14 } 15 16 void dfs(int begin,vector<vector<int>> &res,vector<int> &path,int &sum,vector<int>& candidates) 17 { 18 if( sum == m_target) 19 { 20 res.push_back(path); 21 return; 22 } 23 for(int i = begin;i < candidates.size();++i) 24 { 25 if(sum + candidates[i] > m_target) 26 { 27 break; 28 } 29 sum += candidates[i]; 30 path.push_back(candidates[i]); 31 dfs(i,res,path,sum,candidates); 32 sum -= candidates[i]; 33 path.pop_back(); 34 } 35 return; 36 } 37 private: 38 int m_target; 39 };