做百度竞价对网站空间有什么要求,兰州网络推广关键词优化,linux网站如何做ip解析,中国互联网巨头有哪些LeetCode 78 子集
题目描述
给你一个整数数组 nums #xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集#xff08;幂集#xff09;。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1#xff1a;
输入#xff1a;nums [1,2,3]
输出数组中的元素 互不相同 。返回该数组所有可能的子集幂集。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1
输入nums [1,2,3]
输出[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]示例 2
输入nums [0]
输出[[],[0]]
思路 这道题目和普通的回溯问题的区别在于每加入一次新的元素都要将结果加入result数组中而不是需要判断path数组中的元素是否达到题目要求的标准才加入result数组所以做出的改变就是在for循环的过程中每一次循环都需要加当前的数组加入result中。
代码实现
class Solution {
public:vectorint path;vectorvectorint result;void backtracking(vectorint nums,int startindex){if(path.size() 0) result.push_back(path);if(path.size() nums.size()){return;}for(int i startindex;i nums.size();i){path.push_back(nums[i]);result.push_back(path);backtracking(nums,i 1);path.pop_back();}return;}vectorvectorint subsets(vectorint nums) {backtracking(nums,0);return result;}
};
LeetCode 90 子集II
题目描述
给你一个整数数组 nums 其中可能包含重复元素请你返回该数组所有可能的子集幂集。
解集 不能 包含重复的子集。返回的解集中子集可以按 任意顺序 排列。
示例 1
输入nums [1,2,2]
输出[[],[1],[1,2],[1,2,2],[2],[2,2]]示例 2
输入nums [0]
输出[[],[0]]
思路 子集一问题和子集二问题的区别在于子集二需要进行剪枝。而如何进行剪枝和前面的组合问题是一样的步骤。要去重的是“同一树层上的使用过”如何判断同一树层上元素相同的元素是否使用过了呢。
如果nums[i] nums[i - 1] 并且 used[i - 1] false就说明前一个树枝使用了nums[i - 1]也就是说同一树层使用过nums[i - 1]。
此时for循环里就应该做continue的操作。
这块比较抽象如图 可以看出在nums[i] nums[i - 1]相同的情况下
used[i - 1] true说明同一树枝nums[i - 1]使用过used[i - 1] false说明同一树层nums[i - 1]使用过
used[i - 1] false说明已经进入另一个树枝所以前一个数才会被跳过没有遍历到。而 used[i - 1] true说明是进入下一层递归去下一个数所以是树枝上如图所示 代码实现
class Solution {
public:vectorint path;vectorvectorint result;void backtracking(vectorint nums,int startindex,vectorbool used){if(path.size() 0) result.push_back(path);if(path.size() nums.size()) return;for(int i startindex;i nums.size();i){if(i 0 nums[i] nums[i - 1] used[i - 1] false){continue;}path.push_back(nums[i]);result.push_back(path);used[i] true;backtracking(nums,i 1,used);path.pop_back();used[i] false;}return;}vectorvectorint subsetsWithDup(vectorint nums) {vectorbool used(nums.size(),false);sort(nums.begin(),nums.end());backtracking(nums,0,used);return result;}
}; LeetCode 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]]
思路
递归函数参数
本题求子序列很明显一个元素不能重复使用所以需要startIndex调整下一层递归的起始位置。
代码如下
vectorvectorint result;
vectorint path;
void backtracking(vectorint nums, int startIndex)终止条件
本题其实类似求子集问题也是要遍历树形结构找每一个节点所以可以不加终止条件startIndex每次都会加1并不会无限递归。
但本题收集结果有所不同题目要求递增子序列大小至少为2所以代码如下
if (path.size() 1) {result.push_back(path);// 注意这里不要加return因为要取树上的所有节点
}单层搜索逻辑 在图中可以看出同一父节点下的同层上使用过的元素就不能再使用了。这里避免重复的思路是使用一个unoedered set去判断某一数字在当前树层是否使用过。
那么单层搜索代码如下
unordered_setint uset; // 使用set来对本层元素进行去重
for (int i startIndex; i nums.size(); i) {if ((!path.empty() nums[i] path.back())|| uset.find(nums[i]) ! uset.end()) {continue;}uset.insert(nums[i]); // 记录这个元素在本层用过了本层后面不能再用了path.push_back(nums[i]);backtracking(nums, i 1);path.pop_back();
}
代码实现
class Solution {
public:vectorint path;vectorvectorint result;void backtracking(vectorint nums,int startindex){if(path.size() 1){result.push_back(path);}unordered_setint uset;for(int i startindex;i nums.size();i){if((!path.empty() nums[i] path.back())|| uset.find(nums[i]) ! uset.end()){continue;}uset.insert(nums[i]); path.push_back(nums[i]);backtracking(nums, i 1);path.pop_back();}}vectorvectorint findSubsequences(vectorint nums) {backtracking(nums, 0);return result;}
};