[路飞]递增子序列

91 阅读1分钟

记录 1 道算法题

递增子序列

leetcode-cn.com/problems/in…


要求: 将一个数组里的递增的子数组收集起来,元素可以是不相邻的,每个子数组至少有两个元素。

比如:[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]]

  1. 重复

首先要注意重复的问题。就比如 [4,6,7,7] 里面会有两个 [4,6,7]。去重的方法有很多,我们可以使用 set 进行记录。

  1. 遍历

最简单的做法就是双重遍历。想提升性能的话需要使用递归,首先准备一个记录的数组,推入一个元素之后,进行递归,递归的基础就是当前已经记录的数组元素,然后尝试往里面推入其后面的元素,每次确认一个函数都进行递归。递归结束后将推入的元素进行弹出。所以递归的最小基础模板如下:

    temp = [], nums
    
    for(let i = 0; i < nums.length; i++) {
        // 记录当前最后一位的数字
        temp.push(nums[i])
        // 往后面加一位数字
        dfs()
        // 加完去掉,继续循环,添加下一个
        temp.pop()
    }
    
    比如 [4,6,7,7] 数组的打印
    [4]
    [4,6]
    // 递归结束,下一轮循环
    [4,7]

完整代码如下

    function findSubsequences(nums) {
        const temp = []
        const result = []
        const set = new Set()
        // 开始遍历
        dfs(0, nums, -Infinity, temp, result)
        return result
    }
    
    function dfs(cur, nums, last, temp, result) {
        if (temp.length >= 2) {
            // 每次递归都先将当前的数组存起来,再添加
            result.push(...[temp])
        }
        
        const set = new Set()
        // 以 cur 为起点,尝试将元素推入数组
        for(let i = cur; i < nums.length; i++) {
            const n = nums[i]
            // 比数组的最后一个大
            if (n >= last) {
                // 重复的情况
                if (set.has(n)) continue
                set.add(n)
                temp.push(n)
                // 递归
                dfs(i + 1; nums, n, temp, result)
                temp.pop()
            }
        }
    }