491. 递增子序列

491. 递增子序列

题目链接: 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

解题思路

这道题咋一看挺像90. 子集 II的,所以需要注意两题的区别。90. 子集 II是通过排序来进行去重。但本题不能通过排序来进行去重,因为一旦使用排序,那排序完的得到所有子集都将是递增的,不符合题意(别被第一个示例带偏了)。本题的去重操作可以有两种方法来实现,一是使用unordered_set<int>来记录本层的元素是否重复使用,二是用 数组 记录本层的元素是否重复使用。不过对unordered_set<int> 进行频繁的插入,判断等操作是很费时的。

C++

class Solution {
public:
    vector<int> path;
    vector<vector<int>> result;
​
    void backTracking(vector<int> nums, int start) {
        if (path.size() > 1) {
            // 判断当前序列是否递增(只需判断最后两个数的大小就好,前面的已经判断过)
            if (path[path.size() - 1] >= path[path.size() - 2]) {
                result.push_back(path);
            } else {
                return;
            }
        }
​
        // 对本层元素进行去重(这里使用了集合来实现,还可以用数组来实现(效率更高))
        // visited是记录本层元素是否重复使用,新的一层visited都会重新定义(清空),所以要知道visited只负责本层
        unordered_set<int> visited;
        for (int i = start; i < nums.size(); i++) {
            // 判断当前元素在本层是否已经使用过
            // 使用过
            if (visited.find(nums[i]) != visited.end()) {
                continue;
            }
            // 没使用过
            visited.insert(nums[i]); // 使用该元素,并记录下来,本层的后面不能再用了
            path.push_back(nums[i]);
            backTracking(nums, i + 1);
            path.pop_back();
        }
    }
​
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        path.clear();
        result.clear();
        backTracking(nums, 0);
        return result;
    }
};
class Solution {
public:
    vector<int> path;
    vector<vector<int>> result;
​
    void backTracking(vector<int> nums, int start) {
        if (path.size() > 1) {
                result.push_back(path);
        }
​
        // 用数组来实现去重(效率更高)
        // 题目中说数值范围是[-100,100]
        int visited[201] = {0};
        for (int i = start; i < nums.size(); i++) {
            // 判断当前元素在本层是否已经使用过
            // 使用过,+100是为了将[-100,0]中的值变为正数
            if (visited[nums[i] + 100] == 1) {
                continue;
            }
            // 保证得到的序列是递增序列
            if (path.size() > 0 && nums[i] < path[path.size() - 1]) {
                continue;
            }
            // 没使用过
            visited[nums[i] + 100] = 1; // 使用该元素,并记录下来,本层的后面不能再用了
            path.push_back(nums[i]);
            backTracking(nums, i + 1);
            path.pop_back();
        }
    }
​
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        path.clear();
        result.clear();
        backTracking(nums, 0);
        return result;
    }
};

JavaScript

let path = [];
let result = [];
​
const backTracking = (nums, start) => {
    if (path.length > 1) {
        result.push([...path]);
    }
​
    let visited = new Array(201);
    for (let i = start; i < nums.length; i++) {
        if (visited[nums[i] + 100] === 1) {
            continue;
        }
        if (path.length > 0 && nums[i] < path[path.length - 1]) {
            continue;
        }
        visited[nums[i] + 100] = 1;
        path.push(nums[i]);
        backTracking(nums, i + 1);
        path.pop();
    }
}
​
var findSubsequences = function(nums) {
    path = [];
    result = [];
    backTracking(nums, 0);
    return result;
};

 

 

 

posted @ 2021-12-28 10:40  wltree  阅读(50)  评论(0编辑  收藏  举报