Given a digit string, return all possible letter combinations that the number could represent.
A mapping of digit to letters (just like on the telephone buttons) is given below.
给你这么一堆数字与字母的对应关系,然后给你一段数字组成的字符串,求可能的所有的字母字符串。
Input:Digit string "23" Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
input:string
output:vector<string>
第一反应是利用递归,先算n-1长度的数字的转义+最后一位转义,但是写着写着就懵逼了,因为没办法控制返回值,而且需要全局变量控制vector<string>的长度,最后没有用递归也做出来了。看了一下讨论区的答案,感觉有一篇递归做得很好,拿来学习一下。
class Solution {
public:
vector<string> letterCombinations(string digits)
{
vector<string> res;
if(digits.size()==0) return res;
string local;
vector<vector<char>> table(2,vector<char>());
table.push_back(vector<char>{'a','b','c'}); // index 2
table.push_back(vector<char>{'d','e','f'}); // 3
table.push_back(vector<char>{'g','h','i'});
table.push_back(vector<char>{'j','k','l'}); // 5
table.push_back(vector<char>{'m','n','o'});
table.push_back(vector<char>{'p','q','r','s'}); // 7
table.push_back(vector<char>{'t','u','v'});
table.push_back(vector<char>{'w','x','y','z'}); // 9
backtracking(table,res,local,0,digits);
return res;
}
void backtracking(const vector<vector<char>>& table, vector<string>& res, string& local, int index, const string& digits) {
if(index==digits.size())
res.push_back(local);
else
for(int i=0;i<table[digits[index]-'0'].size();i++) {
local.push_back(table[digits[index]-'0'][i]);
backtracking(table, res, local, index+1, digits);
local.pop_back();
}
}
};
全局变量基本以参数的形式进行传递,通过在递归中加入循环使vector的长度以乘法的速度增长。
string &local local.push_back()和local.pop()控制可变字符串的长度,作为参数继续传递。
==============================================
==============================================
2. 中序遍历的树
给你n个数1234......n,这是一颗二叉树中序遍历的结果,让你求这些树是什么
For example,
Given n = 3, your program should return all 5 unique BST's shown below.
1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
input:n
output:vector<TreeNode*> res
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
TreeNode *clone(TreeNode* s)
{
if (s == nullptr)
return nullptr;
TreeNode *c = new TreeNode(s->val);
c->left = clone(s->left);
c->right = clone(s->right);
return c;
}
vector<TreeNode*> generateTrees(int n) {
vector<TreeNode*> res;
if (n == 0) return res;
if (n == 1)
{
res.push_back(new TreeNode(1));
return res;
}
Recursive(res, n - 1, new TreeNode(n));
return res;
}
void Recursive(vector<TreeNode*> &res,int n,TreeNode* local)
{
if (n == 1)
{
TreeNode *last = new TreeNode(1);
TreeNode *tree_n = clone(local);
TreeNode *local_l = tree_n;
while (local_l->left != nullptr)
{
//进行操作的树为tree_n local_l指向的是tree_n的节点 记录当前local_l的状态
//如果存在左子树local_lt则 local_l-左->lat lat-右->local_lt 对tree_n状态进行更改之后clone出新树进行保存
//local_l-左->local_lt 相当于把tree_n更新回来了。
TreeNode* local_lt = local_l->left;
TreeNode *lat = new TreeNode(n);
local_l->left = lat;
lat->right = local_lt;
TreeNode* restore = clone(tree_n);
res.push_back(restore);
local_l->left = local_lt;
local_l = local_l->left;
}
local_l->left = last;
res.push_back(tree_n);
TreeNode *tree_n_2 = clone(local);
TreeNode *last_2 = new TreeNode(1);
last_2->right = tree_n_2;
res.push_back(last_2);
}
else
{
TreeNode *last = new TreeNode(n);
TreeNode *tree_n = clone(local);
TreeNode *local_l = tree_n;
while (local_l->left != nullptr)
{
TreeNode* local_lt = local_l->left;
TreeNode *lat = new TreeNode(n);
local_l->left = lat;
lat->right = local_lt;
TreeNode* restore = clone(tree_n);
Recursive(res, n - 1, restore);
local_l->left = local_lt;
local_l = local_l->left;
}
local_l->left = last;
Recursive(res, n - 1, tree_n);
TreeNode *tree_n_2 = clone(local);
TreeNode *last_2 = new TreeNode(n);
last_2->right = tree_n_2;
Recursive(res, n - 1, last_2);
}
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
backtrace(root, res);
return res;
}
void backtrace(TreeNode *node, vector<int>& res)
{
if (node == NULL) return;
if (node->left)
{
backtrace(node->left, res);
}
res.push_back(node->val);
backtrace(node->right, res);
}
};
int main()
{
Solution s;
vector<TreeNode*> m = s.generateTrees(5);
for (int i = 0; i < m.size(); i++)
{
vector<int> prt = s.inorderTraversal(m[i]);
for (int j = 0; j < prt.size(); j++)
{
cout << prt[j] << " ";
}cout << endl;
}
}
这题的难点不在递归,递归的规律很好解释,如果是从大到小插入节点比如:n到1
我们最后要得到一颗n节点的树称为tree(n)
对于tree(n)=tree(n-1)+(1个节点)
那么可以是这(一个节点)的右孩子
或者是 对于tree(n-1)每一个左孩子 tree(左孩子) 把(一个节点)插入到tree(左孩子)的位置,然后把tree(左孩子)加入到(1个节点)的右孩子处
难点主要在于指针的运算,由于在递归过程中tree是会各种变化的,因此引入clone函数使tree每次都相当于一个临时变量,且跟之前的tree仅仅是值相同,地址完全不同。
===================================================
===================================================
3.括号匹配
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[ "((()))", "(()())", "(())()", "()(())", "()()()" ]
给你一个数n,然后输出所有合理的匹配括号(即:每个左括号都有右括号匹配)
看起来思路挺多的,其实括号匹配的规律是一共有n个左括号n个右括号,从开始到最后数括号的个数,在每一个位置上,左括号的个数>=右括号的个数
可以选择设置一个函数每次插入括号时判断一下,缺点就是每次都需要遍历你已经写过的括号。能不能每次插入时,括号的个数就是已知的呢?那么这里可以引入递归。
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
string s = "(";
Re(1, 1, 0, n, res, s);
return res;
}
void Re(int len, int a, int b, int n,vector<string>& res,string &local)
{
if (len == 2*n-1)
{
local.push_back(')');
res.push_back(local);
local.pop_back();
return;
}
if (a + 1 <= n)
{
local.push_back('(');
Re(len + 1, a + 1, b, n, res, local);
local.pop_back();
}
if (b + 1 <= a)
{
local.push_back(')');
Re(len + 1, a, b + 1, n, res, local);
local.pop_back();
}
}
};
ab分别是左右括号的个数,len为当前字符串长度
开始肯定是要插入一个左括号的,且最后插入的是右括号,判断好即可。
====================================================
====================================================
Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:
- All numbers (including target) will be positive integers.
- The solution set must not contain duplicate combinations.
For example, given candidate set [2, 3, 6, 7]
and target 7
,
A solution set is:
[ [7], [2, 2, 3] ]
这个题还是想了相当一会儿的,用时大概75min,runtime19ms,大概思路还是递归,首先对原集合排序,
然后对于set(0,n) 表示从第0个数道第n(=size()-1)个数的集合。
比如例子【2,3,6,7】 target=14 根据用没用最后一个数
可以分成 【2,3,6】 target=14 和 【2,3,6,7】 target=7
终止的条件即target=0 或者 对只剩下最后一个元素的判断。
class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> re;
vector<int> res;
sort(candidates.begin(), candidates.end());
bct(candidates,candidates.size() - 1, target, res, re);
return re;
}
void bct(vector<int> nums, int must,int target,vector<int> &res,vector<vector<int>> &re)//nums[must] must in it;
{
if (0 == must)
{
if (target%nums[0] == 0)
{
for (int i = 0; i < target / nums[0]; i++)
res.push_back(nums[0]);
re.push_back(res);
for (int i = 0; i < target / nums[0]; i++)
res.pop_back();
return;
}
else
{
return ;
}
}
else
{
if (target - nums[must] >= 0)
{
res.push_back(nums[must]);
target -= nums[must];
if (target == 0)
{
re.push_back(res);
}
else
{
bct(nums, must, target, res, re);
}
res.pop_back();
bct(nums, must - 1, target+nums[must], res, re);
}
else bct(nums,must-1, target, res, re);
return;
}
}
};
比较麻烦的地方还是pop,push,脑子得清楚。。。想明白递归逻辑之后,这个题就很简单了。
后面还一道差不多的题,我把这个代码改了一点点交上去了,runtime是13ms,用时9min,难度不如上面那题。
Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
Each number in C may only be used once in the combination.
Note:
- All numbers (including target) will be positive integers.
- The solution set must not contain duplicate combinations.
For example, given candidate set [10, 1, 2, 7, 6, 1, 5]
and target 8
,
A solution set is:
[ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]大概意思就是不让重复用数了,其余同上。
class Solution {
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
vector<vector<int>> re;
vector<int> res;
sort(candidates.begin(), candidates.end());
bct(candidates,candidates.size() - 1, target, res, re);
return re;
}
void bct(vector<int> nums, int must,int target,vector<int> &res,vector<vector<int>> &re)//nums[must] must in it;
{
if (0 == must)
{
if (target-nums[0] == 0)
{
res.push_back(nums[0]);
re.push_back(res);
res.pop_back();
return;
}
else
{
return ;
}
}
else
{
if (target - nums[must] >= 0)
{
res.push_back(nums[must]);
target -= nums[must];
if (target == 0)
{
re.push_back(res);
}
else
{
bct(nums, must-1, target, res, re);
}
res.pop_back();
while (must>0&&nums[must] == nums[must - 1]) must--;
if (must>0)
bct(nums, must - 1, target+nums[must], res, re);
}
else
{
while (must>0&&nums[must] == nums[must - 1]) must--;
if(must>0)
bct(nums, must - 1, target, res, re);
}
return;
}
}
};