括号生成
题目:括号生成
思路
何为有效的括号:
1.左括号数量=右括号数量
2.从头开始的任意子串满足,左括号数量 ≥ 有括号数量
- 当左括号数小于对数时,我们可以继续添加左括号;
- 当有括号数小于左括号数时,我们可以继续添加右括号;
- 递归出口,右括号数等于对数时;
C++代码
class Solution
{
int l_count, r_count, n;
string path;
vector<string> ret;
public:
vector<string> generateParenthesis(int _n)
{
n = _n;
dfs();
return ret;
}
void dfs()
{
if(r_count == n )
{
ret.push_back(path);
return;
}
if(l_count < n )
{
path.push_back('(');
l_count++;
dfs();
path.pop_back();
l_count--;
}
if(r_count < l_count)
{
path.push_back(')');
r_count++;
dfs();
path.pop_back();
r_count--;
}
}
};
组合
题目:组合
思路
从1到n中选择k个数的所有组合
dfs(int pos)
每次将当前位置加入path
,并从下一个位置开始递归(剪支)(为了避免重复结果)- 当一次结果
path
长度等于k
时,将其加入到答案中;
C++代码
class Solution
{
vector<vector<int>> ret;
vector<int> path;
int n, k;
public:
vector<vector<int>> combine(int _n, int _k)
{
n = _n;
k = _k;
dfs(1);
return ret;
}
void dfs(int pos)
{
if(path.size() == k)
{
ret.push_back(path);
return;
}
for(int i = pos; i <= n; i++)
{
path.push_back(i);
dfs(i + 1);
path.pop_back();
}
}
};
目标和
题目:目标和
思路
从左往右依次操作每个数的符号,要么加号要么减号
C++代码
class Solution
{
int ret;
int path;
int target;
public:
int findTargetSumWays(vector<int>& nums, int _target)
{
target = _target;
dfs(nums, 0);
return ret;
}
void dfs(vector<int>& nums, int pos)
{
if(pos == nums.size())
{
if(path == target) ret++;
return;
}
path += nums[pos];
dfs(nums, pos + 1);
path -= nums[pos];
path -= nums[pos];
dfs(nums, pos + 1);
path += nums[pos];
}
};
但我们发现这段代码耗时有点多,这是因为我们将
path
放在了全局变量;下面代码我们将其放在dfs()
函数的参数中
class Solution
{
int ret;
int target;
public:
int findTargetSumWays(vector<int>& nums, int _target)
{
target = _target;
dfs(nums, 0, 0);
return ret;
}
void dfs(vector<int>& nums, int pos, int path)
{
if(pos == nums.size())
{
if(path == target) ret++;
return;
}
dfs(nums, pos + 1, path + nums[pos]);
dfs(nums, pos + 1, path - nums[pos]);
}
};
- 当一个结果是整形时,我们最好将其放在
dfs()
函数的参数中; - 因为整形的加减法也是耗时的;
- 当一个结果是保存在数组中时,我们最好将其设置为全局变量;
- 因为每次递归拷贝
vector
也是消耗大的
组合总和
题目:组合总和
思路
上一层选了什么,当前层就从该位置开始选择
- 剪支:当前结果等于目标值时,直接返回,并将其加入答案数组中;
- 当前结果大于于目标值时,直接返回;
- 选完还没有得到结果,直接返回;
C++代码
class Solution
{
vector<vector<int>> ret;
vector<int> path;
int target;
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int _target)
{
target = _target;
dfs(candidates, 0, 0);
return ret;
}
void dfs(vector<int>& candidates, int pos, int sum)
{
if(sum == target)
{
ret.push_back(path);
return;
}
else if(sum > target || pos == candidates.size())
{
return;
}
for(int i = pos; i < candidates.size(); i++)
{
path.push_back(candidates[i]);
dfs(candidates, i, sum + candidates[i]);
path.pop_back();
}
}
};
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » 穷举vs暴搜vs深搜vs回溯vs剪枝(二)
发表评论 取消回复