代码随想录算法训练营第二十八天 491.递增子序列、46.全排列、47.全排列II

代码随想录算法训练营第二十八天 491.递增子序列、46.全排列、47.全排列II

491.递增子序列

题目链接:力扣题目链接

文章讲解:代码随想录(https://programmercarl.com)

视频讲解:回溯算法精讲,树层去重与树枝去重 | LeetCode:491.递增子序列

状态:AC

思路

先查找递增子序列,其次要去重。难点还是在于去重。

查找递增时候,每次需要判断当前的nums[i]是否大于path[-1]

去重和之前的还不大一样,因为这里不可以进行排序。应该判断每层的情况

去重图

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
private:
vector<vector<int>> result;
vector<int> path;

void backTracking(vector<int> &nums, int index) {
if (path.size() > 1) {
result.push_back(path);
}
unordered_set<int> sets;
for (int i = index; i < nums.size(); ++i) {
if ((!path.empty() && path.back() > nums[i]) || sets.find(nums[i]) != sets.end()) {
continue;
}
path.push_back(nums[i]);
sets.insert(nums[i]);
backTracking(nums, i + 1);
path.pop_back();
}
}

public:
vector<vector<int>> findSubsequences(vector<int> &nums) {
backTracking(nums, 0);
return result;
}
};

46. 全排列

题目链接:力扣题目链接

文章讲解:代码随想录(https://programmercarl.com)

视频讲解:组合与排列的区别,回溯算法求解的时候,有何不同?| LeetCode:46.全排列

状态:AC

思路

递归三部曲

保存使用过的数,这里保存的实际上是该数的位置。用的二进制来节省空间。例如,使用了第0个数,括号里指的是该数为二进制,used=1(2)。使用了第0、2个数,那么则是used=101(2),使用了第0、1、3、6个数,used=1001011(2)。即使用了第i个数,used += 1 << i。判断第i个数是否使用过:1 >> i & used

  1. 确立函数和返回值
    • nums
    • used,使用二进制保存
  2. 递归终止条件:path长度等于 nums长度
  3. 单次递归:如果当前的数没被使用过,加入path

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
private:
vector<vector<int>> result;
vector<int> path;

void backTracking(vector<int> &nums, int used) {
if (nums.size() == path.size()) {
result.push_back(path);
return;
}
for (int i = 0; i < nums.size(); ++i) {
if (used >> i & 1) {
continue;
}
path.push_back(nums[i]);
used += 1 << i;
backTracking(nums, used);
path.pop_back();
used -= 1 << i;
}
}

public:
vector<vector<int>> permute(vector<int> &nums) {
int used = 0;
backTracking(nums, used);
return result;
}
};

47. 全排列II

题目链接:力扣题目链接

文章讲解:代码随想录(https://programmercarl.com)

视频讲解:回溯算法求解全排列,如何去重?| LeetCode:47.全排列 II

状态:AC

思路

力扣40题个人博客跳转 + 上一题。used还是使用数组表示。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
private:
vector<vector<int>> result;
vector<int> path;

void backTracking(vector<int> &nums, vector<bool> used2) {
if (nums.size() == path.size()) {
result.push_back(path);
}
for (int i = 0; i < nums.size(); ++i) {

if (i > 0 && nums[i - 1] == nums[i] && !used2[i - 1]) {
continue;
}
if (!used2[i]) {
used2[i] = true;
path.push_back(nums[i]);
backTracking(nums, used2);
path.pop_back();
used2[i] = false;
}
}
}

public:
vector<vector<int>> permuteUnique(vector<int> &nums) {
sort(nums.begin(), nums.end());
vector<bool> used2(nums.size(), false);
backTracking(nums, used2);
return result;
}
};

代码随想录算法训练营第二十八天 491.递增子序列、46.全排列、47.全排列II
https://promisewang.github.io/post/70a8aaa7.html
作者
Promise
发布于
2023年10月20日
许可协议