216.组合总和III
题目链接:216.组合总和III
文档讲解:代码随想录/组合总和III
视频讲解:视频讲解-组合总和III
状态:已完成(1遍)
解题过程
看到题目的第一想法
运用回溯的思维,首先确定终止条件,也就是当前小数组长度等于k,再对当前和sum进行判断,是否为n,如果为n,则ans记录当前小数组,再return;随后用for循环,i=每一层递归的startIndex,在每一层for循环中对小数组和当前sum值进行更新,递归结束之后对sum和小数组进行回溯。这道题如何进行剪枝,我没有想法,想不出来。
手搓代码如下:
/**
* @param {number} k
* @param {number} n
* @return {number[][]}
*/
var combinationSum3 = function(k, n) {
let ans = [],smallArr = [];
// let sum = 0;
const sumThree = function(startIndex,sum){
if(smallArr.length == k){
//如果数组到达k个
if(sum == n){
ans.push(smallArr.slice());
}
return;
}
for(let i = startIndex;i<=9;i++){
smallArr.push(i);
sum += i;
sumThree(i+1,sum);
sum -= i;
smallArr.pop();
}
}
sumThree(1,0);
return ans;
};
提交没有问题,令人意外的是运行时间还不算靠后。
看完代码随想录之后的想法
大体思路没有什么区别!不过剪枝这块倒是学到了,直接在最开始进行一个sum的判断就可以。
讲解代码如下:
/**
* @param {number} k
* @param {number} n
* @return {number[][]}
*/
var combinationSum3 = function(k, n) {
let res = [];
let path = [];
let sum = 0;
const dfs = (path,index) => {
// 剪枝操作
if (sum > n){
return
}
if (path.length == k) {
if(sum == n){
res.push([...path]);
return
}
}
for (let i = index; i <= 9 - (k-path.length) + 1;i++) {
path.push(i);
sum = sum + i;
index += 1;
dfs(path,index);
sum -= i
path.pop()
}
}
dfs(path,1);
return res
};
总结
其实这种剪枝我觉得也可以这样写:
/**
* @param {number} k
* @param {number} n
* @return {number[][]}
*/
var combinationSum3 = function (k, n) {
let ans = [], smallArr = [];
// let sum = 0;
const sumThree = function (startIndex, sum) {
if (smallArr.length == k) {
//如果数组到达k个
if (sum == n) {
ans.push(smallArr.slice());
}
return;
}
for (let i = startIndex; i <= 9; i++) {
smallArr.push(i);
sum += i;
// 和的剪枝
if (sum > n) {
sum -= i;
smallArr.pop();
break;
}
sumThree(i + 1, sum);
sum -= i;
smallArr.pop();
}
}
sumThree(1, 0);
return ans;
};
提交也是没有问题的。
17.电话号码的字母组合
题目链接:17.电话号码的字母组合
文档讲解:代码随想录/电话号码的字母组合
视频讲解:视频讲解-电话号码的字母组合
状态:已完成(1遍)
解题过程
看到题目的第一想法
我能确定的部分是这个N叉树的深度是digits的长度;终止条件就是当前小字符串的长度等于digits的长度。但我想不出来如何建立一个数字和字母对应的关系,也想不出来每次for循环开始时,如何确定从什么字母开始遍历,遍历多少个(7和9对应的字母数量是4个。和别的数字不一样)。
看完代码随想录之后的想法
用了一个数组来创建数字和字母对应关系,再用map[n[a]]来确定每次for循环遍历的那几个字母。
/**
* @param {string} digits
* @return {string[]}
*/
var letterCombinations = function(digits) {
const k = digits.length;
const map = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"];//创建数字和字母的对应关系
if(!k) return [];
if(k === 1) return map[digits].split("");
const res = [], path = [];
backtracking(digits, k, 0);
return res;
function backtracking(n, k, a) {
if(path.length === k) {
res.push(path.join(""));//长度相等,push进结果数组
return;
}
for(const v of map[n[a]]) {
path.push(v);
backtracking(n, k, a + 1);
path.pop();
}
}
};
总结
这道题难点感觉还是不太容易能想到,希望二刷的时候可以记起来。