[路飞]_程序员必刷力扣题: 491. 递增子序列

111 阅读1分钟

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

491. 递增子序列

给你一个整数数组 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

暴力求解+递归

思路 从题目中可以看出我们要求出所有的递增子序列,长度最少为2

那么我们就用递归+遍历的方式来做吧

首先我们可以从示例1中看出,我们可以先求出以4开头的所有结果,再从6开始开头的所有结果,继续遍历下去...直到数组的倒数第二个元素,因为最后一个元素是无法满足题意的

看到4,6,7 我们肯定可以想到会存在两个4,6,7 因为题目中存在两个7,最后必然需要去重,这里我们换了一个方式,用set保存序列化结果,这样就能自动去重了

具体实现:

  • 声明一个res的set数据结构,用来保存所有的序列化结果
  • 声明find函数来进行递归处理,这里接受两个参数,head(已经被选择的元素)和last(剩余未被选择的元素)
    • 在find中我们遍历last,如果满足题意last中的元素item大于head中的最后一个元素,则将item,放入head中,组成一个新的结果newVal,并且序列化保存到res中
    • 接下来我们只需要将刚才的newVal作为一个新的head,将last中还未被选择元素即i之后的元素,重新递归调用find即可
  • 经过find的递归调用我们已经拿到所有以4开头的递增子序列结果,接下来只需要在开头 对nums进行循环,以nums中的每一个元素作为开头进行循环调用find即可
  • 最后我们会得到一个res中保存着所有的序列化结果,遍历res将结果再转为数组放入result中返回即可
var findSubsequences = function (nums) {
    var res = new Set()
    for (var i = 0; i < nums.length - 1; i++) {
        var head = nums[i];
        find([head], nums.slice(i + 1))
    }

    function find(head, last) {
        for (var i = 0; i < last.length; i++) {
            var item = last[i];
            var pre = head[head.length - 1]
            if (item >= pre) {
                var newVal = [...head, item]
                res.add(JSON.stringify(newVal))
                // 开启新篇章
                find(newVal, last.slice(i + 1))
            }
        }
    }
    // 
    var result = []
    for (let item of res) {
        result.push(JSON.parse(item))
    }
    return result
};