[路飞]_leetcode-491-递增子序列

简介: leetcode-491-递增子序列

网络异常,图片无法展示
|


「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战


[题目地址][B站地址]


给你一个整数数组 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 的答案可以看到,它其实就是以每一个元素为起点,向后查找递增子序列,然后将找到的递增子序列放入结果数组即可。这里我们不需要以最后一个元素为起点进行查找,是因为本题要求递增子序列中至少要有两个元素。


基于以上信息,我们就得到了本题的解题思路:


  1. 以除了最后一个元素的每一个元素为起点,向后查找符合条件的元素,组成递增子序列,并将组成的递增子序列插入结果数组。
  2. 在这个过程中,要注意有相同元素的情况,这里我们可以利用 Set 记录已经使用过的数字,如果后面找到的数字已经被使用过,则跳过。


代码实现


var findSubsequences = function(nums) {
  // 记录输入数组长度
  const len = nums.length,
  // 初始化结果数组
  res = [];
  // 根据给定子序列和开始下标,向后查找符合要求的元素,组成新的递增子序列
  function getList(arr,l){
    // 初始化 set 记录使用过的数字
    const set = new Set(),
    // 获取当前子序列最后一个元素
    end = arr[arr.length-1]
    // 遍历未处理区间
    for(let i = l;i<len;i++){
      const item = nums[i]
      // 如果当前数字使用过或者不符合要求,跳过
      if(set.has(item) || item<end) continue;
      // 否则记录该数字
      set.add(item)
      // 获取新的递增子序列
      const _arr = [...arr,item]
      // 将子序列插入结果数组
      res.push(_arr)
      // 继续查找可能的子序列
      getList(_arr,i+1)
    }
  }
  // 创建 set 记录使用过的数字
  const set = new Set();
  // 遍历输入数组,以每一个元素为起点,查找递增子序列
  for(let i = 0;i<len-1;i++){
    const item = nums[i]
    if(set.has(item)) continue
    set.add(item)
    getList([item],i+1)
  }
  // 返回结果数组
  return res;
};
复制代码


至此我们就完成了 leetcode-491-递增子序列


如有任何问题或建议,欢迎留言讨论!👏🏻👏🏻👏🏻

相关文章
|
算法 前端开发