3.6 KiB
3.6 KiB
题目地址
思路
这道题可以说是深度优先搜索,也可以说是回溯法,其实我更倾向于说它用回溯法,因为本题和90. 子集 II非常像,差别就是90. 子集 II可以通过排序,在加一个标记数组来达到去重的目的。
去重复的逻辑,关键在于子序列的末尾,如果子序列的末尾重复出现一个元素,那么该序列就是重复的了,如图所示:
在递归的过程中 if ((subseq.empty() || nums[i] >= subseq.back()) && uset.find(nums[i]) == uset.end()) 这个判断条件一定要想清楚, 如果子序列为空或者nums[i]>=子序列尾部数值,同时 这个nums[i] 不能出现过, 因为一旦出现过就 是一个重复的递增子序列了。
C++代码
class Solution {
private:
void backtracking(vector<int>& nums, vector<vector<int>>& result, vector<int>& subseq, int startIndex) {
if (subseq.size() > 1) {
result.push_back(subseq);
// 注意这里不要加return,因为要取所有的可能
}
unordered_set<int> uset; // 使用set来对尾部元素进行去重
for (int i = startIndex; i < nums.size(); i++) {
if ((subseq.empty() || nums[i] >= subseq.back())
&& uset.find(nums[i]) == uset.end()) {
subseq.push_back(nums[i]);
backtracking(nums, result, subseq, i + 1);
subseq.pop_back();
uset.insert(nums[i]);//在回溯的时候,记录这个元素用过了,后面不能再用了
}
}
}
public:
vector<vector<int>> findSubsequences(vector<int>& nums) {
vector<vector<int>> result;
vector<int> subseq;
backtracking(nums, result, subseq, 0);
return result;
}
};
一位师弟在评论中对代码进行了改进,效率确实高了很多,优化后如图:
改动的地方主要是将去重的逻辑中把 unordered_set 改成了 数组。
用数组替换unordered_set 确实可以快很多,unordered_set底层符号表也是哈希表,理论上不应该差多少。
估计程序运行的时候对unordered_set 频繁的insert,unordered_set需要做哈希映射(也就是把key通过hash function映射为唯一的哈希值)费了些时间。
用数组来做哈希,效率就高了很多,再加上题目中也说了,数值范围[-100,100],所以用数组正合适。
这个事实告诉我们,使用哈希法的时候,条件允许的话,能用数组尽量用数组。
优化后的代码如下:
class Solution {
private:
void backtracking(vector<int>& nums, vector<vector<int>>& result, vector<int>& subseq, int startIndex) {
if (subseq.size() > 1) {
result.push_back(subseq);
// 注意这里不要加return,因为要取所有的可能
}
int hash[201] = {0}; // 这里使用数组来进行去重操作,题目说数值范围[-100, 100]
for (int i = startIndex; i < nums.size(); i++) {
if ((subseq.empty() || nums[i] >= subseq.back())
&& hash[nums[i] + 100] == 0) {
subseq.push_back(nums[i]);
backtracking(nums, result, subseq, i + 1);
subseq.pop_back();
hash[nums[i]+100] = 1;
}
}
}
public:
vector<vector<int>> findSubsequences(vector<int>& nums) {
vector<vector<int>> result;
vector<int> subseq;
backtracking(nums, result, subseq, 0);
return result;
}
};