代码随想录刷题第25天
组合总和 III
/*
* @lc app=leetcode.cn id=216 lang=cpp
*
* [216] 组合总和 III
*
* https://leetcode.cn/problems/combination-sum-iii/description/
*
* algorithms
* Medium (72.08%)
* Likes: 619
* Dislikes: 0
* Total Accepted: 230.3K
* Total Submissions: 319.5K
* Testcase Example: '3\n7'
*
* 找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:
*
*
* 只使用数字1到9
* 每个数字 最多使用一次
*
*
* 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
*
*
*
* 示例 1:
*
*
* 输入: k = 3, n = 7
* 输出: [[1,2,4]]
* 解释:
* 1 + 2 + 4 = 7
* 没有其他符合的组合了。
*
* 示例 2:
*
*
* 输入: k = 3, n = 9
* 输出: [[1,2,6], [1,3,5], [2,3,4]]
* 解释:
* 1 + 2 + 6 = 9
* 1 + 3 + 5 = 9
* 2 + 3 + 4 = 9
* 没有其他符合的组合了。
*
* 示例 3:
*
*
* 输入: k = 4, n = 1
* 输出: []
* 解释: 不存在有效的组合。
* 在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。
*
*
*
*
* 提示:
*
*
* 2 <= k <= 9
* 1 <= n <= 60
*
*
*/
// @lc code=start
#include <vector>
using namespace std;
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void traversal(int k, int n,int index){
if (path.size() == k)
{
int sum = 0;
for (int i = 0; i < k; i++)
{
sum += path[i];
}
if (sum == n)
{
result.push_back(path);
}
}
for (int i = index; i < 10; i++)
{
path.push_back(i);
traversal(k,n,i+1);
path.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
traversal(k,n,1);
return result;
}
};
// @lc code=end
官方的时间复杂度低一点
class Solution {
private:
vector<vector<int>> result; // 存放结果集
vector<int> path; // 符合条件的结果
// targetSum:目标和,也就是题目中的n。
// k:题目中要求k个数的集合。
// sum:已经收集的元素的总和,也就是path里元素的总和。
// startIndex:下一层for循环搜索的起始位置。
void backtracking(int targetSum, int k, int sum, int startIndex) {
if (path.size() == k) {
if (sum == targetSum) result.push_back(path);
return; // 如果path.size() == k 但sum != targetSum 直接返回
}
for (int i = startIndex; i <= 9; i++) {
sum += i; // 处理
path.push_back(i); // 处理
backtracking(targetSum, k, sum, i + 1); // 注意i+1调整startIndex
sum -= i; // 回溯
path.pop_back(); // 回溯
}
}
public:
vector<vector<int>> combinationSum3(int k, int n) {
result.clear(); // 可以不加
path.clear(); // 可以不加
backtracking(n, k, 0, 1);
return result;
}
};
电话号码的字母组合
/*
* @lc app=leetcode.cn id=17 lang=cpp
*
* [17] 电话号码的字母组合
*
* https://leetcode.cn/problems/letter-combinations-of-a-phone-number/description/
*
* algorithms
* Medium (58.05%)
* Likes: 2303
* Dislikes: 0
* Total Accepted: 634.4K
* Total Submissions: 1.1M
* Testcase Example: '"23"'
*
* 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
*
* 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
*
*
*
*
*
* 示例 1:
*
*
* 输入:digits = "23"
* 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
*
*
* 示例 2:
*
*
* 输入:digits = ""
* 输出:[]
*
*
* 示例 3:
*
*
* 输入:digits = "2"
* 输出:["a","b","c"]
*
*
*
*
* 提示:
*
*
* 0 <= digits.length <= 4
* digits[i] 是范围 ['2', '9'] 的一个数字。
*
*
*/
// @lc code=start
#include <string>
#include <vector>
using namespace std;
class Solution {
public:
//映射
const string num2str[10] = {
"",
"",
"abc",
"def",
"ghi", //5
"jkl",
"mno",
"pqrs",
"tuv",
"wxyz"
};
vector<string> result;
string path;
void traversal(string &digits,int index){
if (path.size() == digits.size())
{
result.push_back(path);
return ;
}
int digit = digits[index] - '0';
string s= num2str[digit];
for (int i = 0; i < num2str[digit].size(); i++)
{
path.push_back(s[i]);
traversal(digits,index+1);
path.pop_back();
}
}
vector<string> letterCombinations(string digits) {
result.clear();
if (!digits.size())
{
return result;
}
traversal(digits,0);
return result;
}
};
// @lc code=end
字符串用数组映射,映射后,index代表下一个数字的遍历即可,单独的一个数字就是需要处理的节点,一共3个
第一个有几个选择就处理几个节点,递归的index 是第二个需要排列的索引