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
浙公网安备 33010602011771号