491.递增子序列
给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。
示例:
输入: [4, 6, 7, 7]
输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]
说明:
给定数组的长度不会超过15。
数组中的整数范围是 [-100,100]。
给定数组中可能包含重复数字,相等的数字应该被视为递增的一种情况
思路:
在90.子集II中我们是通过排序,再加一个标记数组来达到去重的目的。
而本题求自增子序列,是不能对原数组经行排序的,排完序的数组都是自增子序列了。
所以不能使用之前的去重逻辑!
class Solution {
public:
vector<int> path;
vector< vector<int>> result;
void backtracking(vector<int>& nums, int startIndex) {
if (path.size() >= 2) {
result.push_back(path);
}
//当遍历到数组最后一位 就结束了
if (startIndex >= nums.size()) return;
unordered_set<int> set;
for (int i = startIndex; i < nums.size(); i++) {
//进行去重以及逻辑判断 find函数返回一个迭代器
//关于set的find函数的返回值find会挨个查找set,当到达set.end()时,也就是一个也没找到,返回end
if (set.find(nums[i]) != set.end()) continue;
if (path.size() == 0 || nums[i] >= path.back()) {
set.insert(nums[i]); //回溯以后不需要擦除set 因为每一层都会重新定义一个set
path.push_back(nums[i]);
backtracking(nums, i + 1);
path.pop_back();
}
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
path.clear();
result.clear();
backtracking(nums, 0);
return result;
}
};
46.全排列
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
思路:
此时就不需要startIndex来确定从数组哪里开始取值
但是需要used数组来判断哪一个元素已经被使用过了,从而达到去重的效果
class Solution {
public:
vector<int> path;
vector<vector<int>> result;
void backtracking(vector<int>& nums,vector<bool>& used) {
if (path.size() == nums.size()) {
result.push_back(path);
return;
}
//used数组,其实就是记录此时path里都有哪些元素使用了,
//一个排列里一个元素只能使用一次。
for (int i = 0; i < nums.size(); i++) {
if (used[i] == true) continue;
path.push_back(nums[i]);
used[i] = true;
backtracking(nums, used);
path.pop_back();
used[i] = false;
}
}
vector<vector<int>> permute(vector<int>& nums) {
path.clear();
result.clear();
vector<bool> used(nums.size(), false);
backtracking(nums,used);
return result;
}
};
47.全排列 II
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
示例 1:
输入:nums = [1,1,2]
输出: [[1,1,2], [1,2,1], [2,1,1]]
示例 2:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
提示:
1 <= nums.length <= 8
-10 <= nums[i] <= 10
横纵都要进行去重 使用一个used数组就可以
class Solution {
public:
vector<int> path;
vector<vector<int>> result;
void backtracking(vector<int>& nums, vector<bool> used) {
if (path.size() == nums.size()) {
result.push_back(path);
return;
}
for (int i = 0; i < nums.size(); i++) {
//去重
//纵向
if (used[i] == true) { continue; }
//横向
// used[i - 1] == true,说明同一树枝nums[i - 1]使用过
// used[i - 1] == false,说明同一树层nums[i - 1]使用过
// 如果同一树层nums[i - 1]使用过则直接跳过
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) continue;
used[i] = true;
path.push_back(nums[i]);
backtracking(nums, used);
used[i] = false;
path.pop_back();
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
path.clear();
result.clear();
vector<bool> used(nums.size(), false);
sort(nums.begin(), nums.end());
backtracking(nums, used);
return result;
}
};