文档讲解:组合总和 组合总和II 分割回文串
题目链接:https://leetcode.cn/problems/combination-sum/description/
思路:
很简单,因为每个数选取的次数为无限个,因此我们在搜索时有两种选取情况:下一步依旧选取当前这个数或者下一步选取下一个位置的数,递归边界条件为位置走到头的时候或者和超过目标值的时候。当和恰好为目标值,证明找到了一种方案。
核心代码:
class Solution {
private:
vector> ans;
vector nums;
vector cand;
int tmp,n;
void dfs(int x,int num){
if(num>tmp) return;
if(num==tmp){
ans.push_back(nums);
return;
}
if(x==n) return;
nums.push_back(cand[x]);
dfs(x,num+cand[x]);
nums.pop_back();
dfs(x+1,num);
}
public:
vector> combinationSum(vector& candidates, int target) {
cand=candidates;
tmp=target;
n=candidates.size();
dfs(0,0);
return ans;
}
};
题目链接:https://leetcode.cn/problems/combination-sum-ii/description/
思路:
本题与上一道题目类似。我们可以预处理下给出的数组,统计每个值出现的次数,将每个值视为只在数组中出现一次,且可多次选取,最多选取次数也已给出。这样的话,我们在递归时在每层将一个值的出现次数用for循环全部枚举完就可以了。
递归边界条件依旧是位置走到头或者和超过目标值的时候。当和恰好为目标值,证明找到了一种方案。
核心代码:
class Solution {
private:
vector> tot;
vector> ans;
vector path;
public:
void dfs(int pos, int rest) {
if (rest == 0) {
ans.push_back(path);
return;
}
if (pos == tot.size() || rest < tot[pos].first) {
return;
}
dfs(pos + 1, rest);
int maxn = min(rest / tot[pos].first, tot[pos].second);
for (int i = 1; i <= maxn; ++i) {
path.push_back(tot[pos].first);
dfs(pos + 1, rest - i * tot[pos].first);
}
for (int i = 1; i <= maxn; ++i) {
path.pop_back();
}
}
vector> combinationSum2(vector& candidates, int target) {
sort(candidates.begin(), candidates.end());
for (int num: candidates) {
if (tot.empty() || num != tot.back().first) {
tot.emplace_back(num, 1);
} else {
++tot.back().second;
}
}
dfs(0, target);
return ans;
}
};
题目链接:https://leetcode.cn/problems/palindrome-partitioning/description/
思路:
本题目我们可以像分割区间那样枚举,是否能分割则需要判断分割掉的区间是否是回文串。比方说我们现在[1,a]的区间已经分割好了,分割成了多少段我不需要管,下面需要分割[a+1,n],我就分别从 a+1,a+2,a+3......等处分割,是否可以分割取决于 [a+1,a+1],[a+1,a+2],[a+1,a+3]......是否是回文串。
递归边界条件为分割线位置走到最后,同时分割线走到最后也证明前面全部分割成功为回文子串。
核心代码:
class Solution {
private:
vector> result;
vector path;
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();
}
}
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;
}
public:
vector> partition(string s) {
result.clear();
path.clear();
backtracking(s, 0);
return result;
}
};
今日学习时长3h,题目不算简单。昨天高烧,今天还在打针,勉强做了一下写了一下。