491. Increasing Subsequences

在这里插入图片描述
很明显,用dfs来做。但问题是如何避免重复的答案。
我想了很多,比如标记重复值出现的位置,只有第一个重复值被用到时后面的重复值才能够被使用,但总感觉不太对。

看了discuss区的解法,先上代码:

class Solution {
public:
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        vector<vector<int>> ret;
        vector<int> temp;
        helper(ret, nums, temp, 0);
        return ret;
    }
private:
    void helper(vector<vector<int>>& ret, vector<int>& nums, vector<int>& temp, int index) {
        if (temp.size() >= 2)
            ret.push_back(temp);
        unordered_set<int> s; //保证了对于同一个前缀(也就是调用到这儿的时候),temp的当前位置不会放相同的数字
        for (int i = index; i < nums.size(); ++i) {
            if (s.find(nums[i]) != s.end())
                continue;
            if (temp.empty() || temp.back() <= nums[i]) {
                s.insert(nums[i]);
                temp.push_back(nums[i]);
                helper(ret, nums, temp, i+1);
                temp.pop_back();
            }
        }
    }
};

第一次写类似这样的dfs,这里的set的作用是:
保证对于temp中同一个前缀,temp的当前位置不会放相同数字。

dfs是树型的调用,比如调用的第一层时,temp第一个位置的数字不应该重复,因为相同的数字的话有一个就把所有情况都考虑到了,再来一个相同的就会多余,所以对于前缀为空的情况是,这里的set会保证第一个位置的数字不会有相同的;调用到某一层时,这时前缀不为空,这时的set可以保证在这个前缀的情况下,temp的下一个位置不会放相同的数字,道理同上。

//这个方法和之前自己熟悉的visited,看前面一个相同的有没有用到的解法的区别是:这里不允许sort,那么相同的数字不会到一块。造成的后果是只能检测出恰好连在一起的相同数字导致的重复,对于不连在一起的无能为力。其实目的就是同一个位置,不能重复放相同的元素。
//这里的使用set的方法应该是一个更加通用的解法(也就是说用在前面的情况也适合,不过不如visited简便),它是对于同一个前缀来说,当前位置不能重复放相同的数字。这是能够解决重复数字不放在一起的。

//所以说,如果以后如果要思考如何去重,从根源想起的话,应该是:每个位置不能放相同元素。如果允许排序,那么可以使用visited的方法。如果不行,就是用这里的set的方法。

注意:这一题可以这样写是有特殊性的,不是每一题都可以这样写的。
特殊性在于要求求出来的序列是有序的,这保证了不会有倒序但相同的集合出现。
用在其他地方时,这种set的用法,要注意需要先排序(既然这样,不如直接用visited[]。。。)。
见:https://blog.csdn.net/weixin_43462819/article/details/84453981

posted @ 2019-06-03 15:47  于老师的父亲王老爷子  阅读(19)  评论(0)    收藏  举报