39. 组合总和
计算一个vector的总和有没有简单的方法。。每次都单独写一个函数出来
待补充:
class Solution {
public:
vector<vector<int>> result;
vector<int> each;
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backTrace(target, candidates, 0);
return result;
}
void backTrace(int target, vector<int>& candidates, int index) {
int sum = getSum(each);
if (sum > target) {
return;
}
if (sum == target) {
result.push_back(each);
return;
}
int n = candidates.size();
for (int i = index; i < n; ++i) {
each.push_back(candidates[i]);
backTrace(target, candidates, i);
each.pop_back();
}
}
int getSum(vector<int> each) {
int n = each.size();
int sum = 0;
for (int i = 0; i < n; ++i) {
sum += each[i];
}
return sum;
}
};
40 组合总和 II
本来以为很容易可以AC。。没想到题中的数组虽然不能一个数用多次,但有重复的数啊。。
be like:
决定先排序再去重
unordered_set貌似没法去重vector<int>
看了下真的用哈希表去重很容易超时
题解:
可以看出添加了used数组专门用来记录同一层用过的重复元素
//
class Solution {
public:
vector<vector<int>> result;
vector<int> each;
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
vector<bool> used(candidates.size(), false);
backTrace(candidates, target, 0, used);
return result;
}
void backTrace(vector<int>& candidates, int target, int index,
vector<bool>& used) {
int sum = getSum(each);
if (sum == target) {
result.push_back(each);
return;
}
if (sum > target) {
return;
}
int n = candidates.size();
for (int i = index; i < n; ++i) {
if (i > 0 && candidates[i] == candidates[i - 1] &&
used[i - 1] == false) {
continue;
}
each.push_back(candidates[i]);
used[i] = true;
backTrace(candidates, target, i + 1, used);
used[i] = false;
each.pop_back();
}
}
int getSum(vector<int> each) {
int n = each.size();
int sum = 0;
for (int i = 0; i < n; ++i) {
sum += each[i];
}
return sum;
}
};
注意构造数组用法:vector<bool> used(candidates.size(), false);
剪枝:
for (int i = index; i < n && getSum(each)+candidates[i]<=target ; ++i) {
131 分割回文串
注意字符串反转函数,(algorithm中)
reverse(each.begin(), each.end())
注意
在主函数调用回溯函数之前先把两个全局变量清空(因为全局变量初始化之前没有赋值)
result.clear();
path.clear();
substr()写的有问题,第一位参数是起始位置,第二位是字符串长度(不是结束位置)
class Solution {
public:
vector<string> each;
vector<vector<string>> result;
vector<vector<string>> partition(string s) {
each.clear();
result.clear();
backTrace(s, 0);
return result;
}
void backTrace(string s, int index) {
int n = s.size();
if (index >= n) {
result.push_back(each);
return;
}
for (int i = index; i < n; ++i) {
string curr = s.substr(index, i -index + 1);
if (isReverse(curr) == true) {
each.push_back(curr);
backTrace(s, i+1);
each.pop_back();
}
}
return;
}
bool isReverse(string each) {
int n = each.size();
int begin = 0;
int end = n - 1;
while (begin < end) {
if (each[begin] != each[end]) {
return false;
}
begin++;
end--;
}
return true;
// string curr = each;
// reverse(curr.begin(),curr.end());
// if(curr==each) return true;
// return false;
}
};
93.复原IP地址
跟上一题真的很类似但是不知道为什么第一版写的就是each存入不进result。。。感觉逻辑也没啥问题
class Solution {
public:
vector<string> result;
string each= "";
vector<string> restoreIpAddresses(string s) {
// result.clear();
// each.clear();
backTrace(s, 0);
return result;
}
void backTrace(string s, int index){
int n = s.size();
if(each.size() > n+3){
return;
}//感觉不加也行,加了算是剪枝?
if(index >= n ){
if(each.size() == n+3){
result.push_back(each);
}
return;
}
for(int i = index; i<n; ++i){
string curr = s.substr(index, i-index+1);
if(isValid(curr)==true){
string save = each;
each += '.';
each += curr;
backTrace(s, i+1);
each.erase(each.begin() + i + 1);
}
else break;
}
}
bool isValid(string curr){
int n = curr.size();
if(n==0 || n>3 ){
return false;
}
if(n>1 && curr[0]=='0' ){
return false;
}
int currNum =0;
for(int i=n; i>=0;--i){
if(curr[i] <'0' || curr[i] > '9'){
return false;
}
currNum += (curr[i]-'0')*pow(10,n-i);
if(currNum>255){
return false;
}
}
return true;
}
};
清空重写
注意:
s.insert()
s.erase()
class Solution {
public:
vector<string> result;
vector<string> restoreIpAddresses(string s) {
backTrace(s,0,0);
return result;
}
void backTrace(string& s, int index, int pointSum){
if(pointSum==3){
string last = s.substr(index, s.size()-index);
if(isValid(last)==true){
result.push_back(s);
}
return;
}
for(int i = index; i<s.size(); ++i){
string curr = s.substr(index, i-index+1);
if(isValid(curr)==true){
pointSum++;
s.insert(s.begin()+i+1, '.');
backTrace(s,i+2, pointSum);
pointSum--;
s.erase(s.begin()+i+1);
}
else{
break;
}
}
}
bool isValid(string curr){
int n = curr.size();
if(n<=0 || n >3){
return false;
}
if(n>1 && curr[0]=='0'){
return false;
}
int sum = 0;
int num = 1;
for(int i = n-1 ; i>=0 ; --i){
if(curr[i] < '0' || curr[i] > '9'){
return false;
}
sum += (curr[i]-'0') * (num);
num = num *10;
if(sum > 255){
return false;
}
}
return true;
}
};
AC
78.子集
普通回溯算法,巧思是有可能这一步啥也不选,因此在数组最后加一个0,如果index到最后一位了且当前为0,那么啥也不用push,直接回溯,也不用pop
class Solution {
public:
vector<vector<int>> result;
vector<int> each;
vector<vector<int>> subsets(vector<int>& nums) {
nums.push_back(0);
backTrace(0,nums);
return result;
}
void backTrace(int index, vector<int>& nums){
int n = nums.size();
if(index >=n){
result.push_back(each);
return;
}
for(int i = index ; i<n; ++i){
if(i==n-1 && nums[i]==0){
backTrace(i+1, nums);
}
else{
each.push_back(nums[i]);
backTrace(i+1, nums);
each.pop_back();
}
}
}
};
AC