一、491 递增子序列
思路:见代码注释
代码:
var findSubsequences = function(nums) {
var result = [];
var backtracking = function(startIndex, path) {
// 很像子集问题,应该收集所有的子节点,但是长度不能为一
if (path.length > 1) {
result.push(path.slice(0));
}
// 数组的范围是[-100, 100],因此下面也需要加100
let used = [];
for (let i=startIndex; i<nums.length; i++) {
// 看树,如果当前的数字比path的最后一个数要小
// 或者当前的数字已经被用过了的话,那么就跳过
if (path.length > 0 && nums[i] < path[path.length - 1] || used[nums[i] + 100]) {
continue;
}
used[nums[i] + 100] = true;
path.push(nums[i]);
backtracking(i + 1, path);
path.pop();
}
}
backtracking(0, []);
return result;
};
二、46 全排列
思路:主要是判断目前的数字在之前有没有用过,因为题目说了是不含重复数字的数组,所以可以直接判断path中是否有加入过这个数
代码:
var permute = function(nums) {
var result = [];
var backtracking = function(path) {
if (path.length == nums.length) {
result.push(path.slice(0));
return;
}
for (let i=0; i<nums.length; i++) {
// 因为不含重复数字,所以可以这样判断是否已经读过一遍了
if (path.indexOf(nums[i]) !== -1) {
continue;
}
path.push(nums[i]);
backtracking(path);
path.pop();
}
}
backtracking([]);
return result;
};
三、47 全排列II
思路:将两种去重方式结合起来
代码:
var permuteUnique = function(nums) {
nums.sort((a, b) => a - b);
var result = [];
var backtracking = function(used, path) {
if (path.length == nums.length) {
result.push(path.slice(0));
return;
}
for (let i=0; i<nums.length; i++) {
if (i>0 && nums[i] === nums[i-1] && !used[i-1]) {
continue;
}
if (!used[i]) {
used[i] = true;
path.push(nums[i]);
backtracking(used, path);
path.pop();
used[i] = false;
}
}
}
backtracking([], []);
return result;
};
今日学习时长:1.5h左右
总结:47需要再看,回溯告一段落但是以后得经常来看看,练习一下。