目录
Leetcode 491.递增子序列
题目链接:Leetcode 491.递增子序列
题目描述:给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。注:给定数组中可能包含重复数字,相等的数字应该被视为递增的一种情况。
思路:本题数组中包含重复数字,之前面对重复数组的应对措施是:先排序在根据相邻元素是否相同这个逻辑去重。不过这道题就不能这么做了,如果先排序的话,要么全是递增,要么全是递减,和我们需要的结果大相径庭。因此我们需要使用STL的哈希表或者用一个数组来记录该元素是否被使用过,再通过回溯来求出结果。
代码如下:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, int start) {
if (path.size() > 1) {//如果子序列长度大于等于2,就收集一个结果
result.push_back(path);
}
int used[210] = {0}; //使用数组来进行去重操作(题干数据范围为[-100,100],保险一点多开一点数组)
for (int i = start; i < nums.size(); i++) {
//去重部分
if ((!path.empty() && nums[i] < path.back()) || used[nums[i] + 100] == 1) {
continue;
}
used[nums[i] + 100] = 1;
path.push_back(nums[i]);
backtracking(nums, i + 1);
path.pop_back();
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
backtracking(nums, 0);
return result;
}
};
Leetcode 46.全排列
题目链接:Leetcode 46.全排列
题目描述:给定一个没有重复数字的序列,返回其所有可能的全排列。
思路:题干强调没有重复元素,那就非常好办了,直接利用回溯遍历从头序列,不过需要注意的是要将path内部的元素打上标记,这样就不会重复选自己了。
代码如下:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, vector<bool>& used) {
if (nums.size() == path.size()) {//某次path与数组大小相同说明找到一个答案
result.push_back(path);
return;
}
for (int i = 0; i < nums.size(); i++) {
if (used[i] == true)
continue;
used[i] = true;
path.push_back(nums[i]);
backtracking(nums, used);
path.pop_back();
used[i] = false;
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<bool> used(nums.size(), false);
backtracking(nums, used);
return result;
}
};
Leetcode 47.全排列 II
题目链接:Leetcode 47.全排列 II
题目描述:给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
思路:由于这道题有重复元素,并且不像这道题Leetcode 491.递增子序列不能改变原数组,因此可以先将nums排列,再根据相邻元素是否相同就可以实现去重了。然后和Leetcode 46.全排列的思路完全一致了。
代码如下:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, vector<bool>& used) {
if (nums.size() == path.size()) {
result.push_back(path);
return;
}
for (int i = 0; i < nums.size(); i++) {
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
continue;
}
if (used[i] == false) {
used[i] = true;
path.push_back(nums[i]);
backtracking(nums, used);
used[i] = false;
path.pop_back();
}
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end()); //排序有利于去重逻辑的书写
vector<bool> used(nums.size(), false);
backtracking(nums, used);
return result;
}
};
总结:今天主要是辨析对于含有相同元素的排序问题,如何实现去重操作:
(1)对于寻找序列元素的子集等排序问题,可以先将序列排序,再根据相同元素相邻这一性质去重。
(2)对于寻找序列元素之间大小关系等排序问题,比如求递增,递减序列,应该利用哈希表记录来去重。如果改变了序列元素之间的相对关系(例如排序),就没办法做了。
最后,如果文章有错误,请在评论区或私信指出,让我们共同进步!