目录
合法括号
思路:首先我们要找出规律,然后写出递归式。这个题通过画图我们会得到Sn={对Sn-1中每个元素进行添左,添右,添包,左和右肯定会重复,我们可以用STL标准库中的set进行去重.
递归
#include<iostream>
#include<set>
using namespace std;
set<string> generateParenthesis(int n) {
set<string> s_n;
if (n == 1)
{
s_n.insert("()");
return s_n;
}
set<string> s_n_1 = generateParenthesis(n - 1);
for (string eofn_1 : s_n_1)
{
s_n.insert("()" + eofn_1);
s_n.insert(eofn_1 + "()");
s_n.insert("(" + eofn_1 + ")");
}
return s_n;
}
int main()
{
set<string> generateParenthesis1 = generateParenthesis(4);
for (set<string>::iterator it = generateParenthesis1.begin(); it != generateParenthesis1.end(); it++)
{
cout << *it << " ";
}
return 0;
}
迭代
set<string> generateParenthesis2(int n) {
set<string> res;
res.insert("()");
if (n == 1)
{
return res;
}
for (int i = 2; i <= n; i++)
{
set<string> res_new;
for (string e : res)
{
res_new.insert(e + "()");
res_new.insert("()" + e);
res_new.insert("(" + e + ")");
}
res = res_new;
}
return res;
}
牛刀小试
扫描二维码关注公众号,回复:
13760498 查看本文章
所有子集
思路:
如果集合中共有 n 个元素,那么确定集合的子集共需要 n 步。每一步都需要从集合中取出一个元素,这时候存在两个选择,添加当前数字或者不添加。生成一个子集需要若干步,并且每一步都有若干种选择,这是应用回溯法的典型问题。
代码中 helper 函数共有四个参数,第一个参数是原数组 nums,第二个参数是当前需要选择的数字在 nums 数组内的下标 index,第三个参数是当前子集 cur,第四个参数是当前已经生成的子集的集合 ret。
对于 nums 数组内的下标 index 的数字,当前有两种选择。第一种是不考虑加入,那么可以直接跳过,调用递归函数判断 index + 1 的情况。第二种是考虑加入,那么将该数字加入当前子集 cur 中,接着调用递归函数判断 index + 1 的情况,递归函数执行完之后,还需要将加入的数字删除,这样才能使当前子集 cur 在进入当前递归函数之后和执行完当前递归函数之后的值保持不变。
递归
class Solution {
private:
void helper(vector<int>& nums, int index, vector<vector<int>>& ret, vector<int>& cur) {
if (index == nums.size()) {
ret.emplace_back(cur);
return;
}
// 不加入第 index 个数字
helper(nums, index + 1, ret, cur);
// 加入第 index 个数字
cur.push_back(nums[index]);
helper(nums, index + 1, ret, cur);
cur.pop_back();
}
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> ret;
vector<int> cur;
helper(nums, 0, ret, cur);
return ret;
}
};