跳转至

491. 非递减子序列

力扣链接(中等):https://leetcode.cn/problems/non-decreasing-subsequences

给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。

数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。

示例 1:

Text Only
输入: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:

Text Only
输入:nums = [4,4,3,2,1]
输出:[[4,4]]

提示:

  • 1 <= nums.length <= 15
  • -100 <= nums[i] <= 100

个人题解

  • 此题建议和「40. 组合总和II」的去重逻辑对比;
  • 之所以这里要用 set 来去重,因为这里不能对 nums 排序;
  • 由于本题 -100 <= nums[i] <= 100 数据不够分散,其实用数组即可,不必用效率不高的 STL。
C++
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;

    void backtracking(const vector<int> &nums, int begin) {
        if(path.size() > 1) result.push_back(path);
        if(begin >= nums.size()) return;

        // 此题建议和「40. 组合总和II」的去重逻辑对比
        // 之所以这里要用 set 来去重,因为这里不能对 nums 排序
        // 优化:由于本题 -100 <= nums[i] <= 100 数据不够分散,其实用数组即可,不必用效率不高的 STL
        unordered_set<int> used;
        for(int i = begin; i < nums.size(); i++) {
            // 判断当前元素是否满足递增,判断是否在当前层已使用
            if((!path.empty() && path.back() > nums[i]) || 
            used.count(nums[i])) continue;

            path.push_back(nums[i]);
            used.insert(nums[i]);
            backtracking(nums, i + 1);
            // 注意这里不用 used.erase
            // 因为 set 仅在当前层生效,作用域仅在某一层 (for) 中
            path.pop_back();
        }
    }
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        backtracking(nums, 0);
        return result;
    }
};