算法训练day29 LeetCode 39.40.131
39.组合总和
题目
题解
-
class Solution { private: vector<vector<int>> result; vector<int> path; void backtracking(vector<int> &candidates, int target, int sum, int startIndex) { if (sum > target) return; if (sum == target) { result.push_back(path); } for (int i = startIndex; i < candidates.size(); i++) { sum += candidates[i]; path.push_back(candidates[i]); backtracking(candidates, target, sum, i); sum -= candidates[i]; path.pop_back(); } } public: vector<vector<int>> combinationSum(vector<int> &candidates, int target) { result.clear(); path.clear(); backtracking(candidates, target, 0, 0); return result; } };
-
在sum>target时,依然会进入下一层循环,所以可以添加一个剪枝
-
void backtracking(vector<int> &candidates, int target, int sum, int startIndex) { // if (sum > target) // return; if (sum == target) { result.push_back(path); return; } for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) //剪枝 { sum += candidates[i]; path.push_back(candidates[i]); backtracking(candidates, target, sum, i); sum -= candidates[i]; path.pop_back(); } }
40.组合总和II
题目
题解
-
candidates 中元素重复、单个结果中元素可以重复、总结果集中不能有结果重复
-
需要去重 ---> 将组合的形式以树形结构组织
- 单个结果元素可重复 ---> 单次组合(单枝)中不需要去重
- 多个结果之间不能重复 ---> 不同次组合(同一层)中需要去重 ---> 将元素排序之后组合实现去重
-
class Solution { private: vector<vector<int>> result; vector<int> path; void backtracking(vector<int> &candidates, int target, int sum, int startIndex, vector<bool> used) { if (sum == target) { result.push_back(path); return; } for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) { if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) //同层去重 continue; sum += candidates[i]; path.push_back(candidates[i]); used[i] = true; backtracking(candidates, target, sum, i + 1, used); used[i] = false; sum -= candidates[i]; path.pop_back(); } } public: vector<vector<int>> combinationSum2(vector<int> &candidates, int target) { vector<bool> used(candidates.size(), false); result.clear(); path.clear(); sort(candidates.begin(), candidates.end()); backtracking(candidates, target, 0, 0, used); return result; } };
131.分割回文串
题目
题解
-
递归用来纵向遍历,for循环用来横向遍历,切割线(就是图中的红线)切割到字符串的结尾位置,说明找到了一个切割方法。
-
class Solution { private: vector<vector<string>> result; vector<string> path; bool isPalindrome(const string &s, int start, int end) { for (int i = start, j = end; i < j; i++, j--) { if (s[i] != s[j]) return false; } return true; } void backtracking(const string &s, int startIndex) { if (startIndex >= s.size()) { result.push_back(path); return; } for (int i = startIndex; i < s.size(); i++) { if (isPalindrome(s, startIndex, i)) { string str = s.substr(startIndex, i - startIndex + 1); path.push_back(str); } else continue; backtracking(s, i + 1); path.pop_back(); } } public: vector<vector<string>> partition(string s) { result.clear(); path.clear(); backtracking(s, 0); return result; } };