1、二叉树中和为某一值的路径
本题考点: 简单回溯法的使用 牛客链接
题目描述:
输入一颗二叉树的根节点root和一个整数expectNumber,找出二叉树中结点值的和为expectNumber的所有路径。
1.该题路径定义为从树的根结点开始往下一直到叶子结点所经过的结点
2.叶子节点是指没有子节点的节点
3.路径只能从父节点到子节点,不能从子节点到父节点
4.总节点数目为n
如二叉树root为{10,5,12,4,7},expectNumber为22
则合法路径有[[10,5,7],[10,12]]
数据范围:
树中节点总数在范围 [0, 5000] 内
-1000 <= 节点值 <= 1000
-1000 <= expectNumber <= 1000
解题思路:
代码:
class Solution {
public:
void FindPathDFS(TreeNode* root,int expectNumber,vector<vector<int>>& result, vector<int>& path)
{
if(root == nullptr)
return;
path.push_back(root->val); //添加结果到待选结果中
expectNumber -= root->val; //更新条件
if(root->left == nullptr && root->right == nullptr && expectNumber == 0)
{
result.push_back(path); //合法则保存路径
}
//DFS 深度优先
FindPathDFS(root->left, expectNumber, result, path);
FindPathDFS(root->right, expectNumber, result, path);
path.pop_back(); //回溯 (此处不想手动删除的话,参数可以传值)
}
vector<vector<int>> FindPath(TreeNode* root,int expectNumber) {
vector<vector<int>> result;
vector<int> path;
FindPathDFS( root, expectNumber, result, path);
return result;
}
};
2、字符串的排列
本题考点: 全排列问题,DFS 牛客链接
题目描述:
输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。
解题思路:
代码:
class Solution {
public:
bool isExit(vector<string>& v, string str)
{
for(int i = 0; i < v.size(); i++)
{
if(v[i] == str)
return true;
}
return false;
}
void _Permutation(string& str, int start, vector<string>& result)
{
//返回条件
if(start == str.length() - 1)
{
//去重
if(!isExit(result, str))
result.push_back(str);
return;
}
for(int i = start; i < str.length(); i++)
{
swap(str[start], str[i]); //以i对应的字符作为开始
_Permutation(str, start + 1, result); //以i开头的所有可能全部处理并保存到了result中
swap(str[start], str[i]);
}
}
vector<string> Permutation(string str) {
vector<string> result;
if(!str.empty())
{
_Permutation(str, 0, result);
sort(result.begin(), result.end());
}
return result;
}
};
3、电话号码的字母组合
本题考点: 回溯,DFS(深度优先) 牛客链接
题目描述:
九键输入法中 2~9 每个数字对应了若干个的字母,请找出给定数字组合对应的全部字母组合。
1.该题你返回的组合顺序可以不唯一
2.该题你返回的字母大小写都是可以的 (最好小写,大写用例通过不了)
数据范围:数字长度1≤n≤5 ,数字中保证不出现 0 和 1
键盘数字对应的映射如下:
解题思路:
代码:
class Solution {
public:
//vector<string> v {"", "", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ"};
vector<string> v {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
void _phoneNumber(string num, int i, string combineStr, vector<string>& retV)
{
if(i == num.size()) // 控制的是行数,等于num.size()说明最后一组数走完了
{
retV.push_back(combineStr);
return;
}
string str = v[num[i] - '0'];
for(int j = 0; j < str.size(); j++) //j控制的是列数
{
_phoneNumber(num, i + 1, combineStr + str[j] , retV);
}
}
vector<string> phoneNumber(string num) {
vector<string> retV;
if(num.empty())
return retV;
string combineStr = "";
_phoneNumber(num, 0, combineStr, retV);
return retV;
}
};
4、最小的K个数
本题考点: topK问题 牛客链接
题目描述:
给定一个长度为 n 的可能有重复值的数组,找出其中不去重的最小的 k 个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4(任意顺序皆可)。
数据范围:0≤k,n≤10000,数组中每个数的大小0≤val≤1000
要求:空间复杂度 O(n) ,时间复杂度O(nlogk)
解题思路:
代码:
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
priority_queue<int> pqe (input.begin(), input.begin() + k);
vector<int> retV;
if(input.empty() || k == 0)
return retV;
//将[k, input.size())元素以此跟堆顶元素比较
for(int i = k; i < input.size(); i++)
{
if(input[i] < pqe.top())
{
pqe.pop();
pqe.push(input[i]);
}
}
for(int i = 0; i < k; i++)
{
retV.push_back(pqe.top());
pqe.pop();
}
return retV;
}
};