题目描述
给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。
数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。
示例 1:
输入: nums = [4,6,7,7]
输出: [[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]
示例 2:
输入: nums = [4,4,3,2,1]
输出: [[4,4]]
提示:
1 <= nums.length <= 15-100 <= nums[i] <= 100
解题思路
首先我们观察示例1 的答案可以看到,本题的递增子序列,并不是严格递增,后面的元素是可以等于前面的元素的。
第二点,是关于本题的提示,如果含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。这句话的意思其实是说我们的答案中,不允许有重复的元素。比如前面的 4,6 可以和第一个 7 组成 4,6,7,也可以和第二个 7 组成 4,6,7,但是我们的结果数组中只有一个 4,6,7,所以我们要对结果去重。
接下来我们再观察示例1 的答案可以看到,它其实就是以每一个元素为起点,向后查找递增子序列,然后将找到的递增子序列放入结果数组即可。这里我们不需要以最后一个元素为起点进行查找,是因为本题要求递增子序列中至少要有两个元素。
基于以上信息,我们就得到了本题的解题思路:
- 以除了最后一个元素的每一个元素为起点,向后查找符合条件的元素,组成递增子序列,并将组成的递增子序列插入结果数组。
- 在这个过程中,要注意有相同元素的情况,这里我们可以利用
Set记录已经使用过的数字,如果后面找到的数字已经被使用过,则跳过。
代码实现
var findSubsequences = function(nums) {
let res = [];
let len = nums.length;
const set = new Set();
// 去重函数
const dfs = (start,path) =>{
if(path.length >= 2){
// 将path数组转换成字符串
const str = path.toString();
if(!set.has(str)){//当前set里面没有当前的path
// 放进去一个拷贝的path
res.push(path.slice())
// 存入set里面,记录一下
set.add(str);
}
}
// 枚举出当前所有可能会出现的序列情况,从start一直到数组的末尾;
for(let i = start; i < len; i++){
// 上一个选择,就是path数组里面的末尾元素
const prev = path[path.length -1];
// 当前的序列
const cur = nums[i];
// 开始判断是否满足递增关系;
if(path.length == 0 || prev <= cur){//path是空的或者满足递增关系
// cur就是当前的数字
path.push(cur);
// 往下递归
dfs(i + 1,path);
path.pop();//删除当前数字,选择新的数字
}
}
}
//递归的入口,从下标为0到数组的最后一位,将这些合适的数字,带有递增关系的序列加到path;path初始化为空;
dfs(0,[]);
return res;
};
至此我们就完成了leetcode-491-递增子序列