灵神【基础算法精讲】视频的个人笔记。
视频例题
46.全排列
组合无顺序。从1,2,3中选两个
flowchart TB
1 --> 1,2 & 1,3
2 --> 2,3
在1时,选比1大的2和3。在2时,选比2大的3,不需要再选1,2,1跟1,2一样,重复了。
//一个循环即可,下一个数 选比当前数大的数
for(int j = i; j < 3; ++j) //i为当前选的数
但是全排列有顺序。从1,2,3中选两个
flowchart TB
1 --> 1,2 & 1,3
2 --> 2,1 & 2,3
在2时,仍然要选1,与2的大小无关。这时就需要一个布尔数组on_path,表示是否已经选过(在路径上)。
class Solution {
public:
vector<vector<int>> ans;
vector<int> path, nums;
vector<bool> on_path;
int n;
void dfs(int i) {
if(i >= n) {
ans.emplace_back(path);
return;
}
for (int j = 0; j < n; ++j) {
if(on_path[j]) continue; //已在path上
path.emplace_back(nums[j]);
on_path[j] = true;
dfs(i + 1);
path.pop_back(); //恢复
on_path[j] = false;
}
}
vector<vector<int>> permute(vector<int>& _nums) {
nums = _nums;
n = _nums.size();
vector<bool> on(n, false);
on_path = on;
dfs(0);
return ans;
}
};
51.N 皇后
三个条件
- 不能同一行
- 那么每次在一行中选一个皇后就行了。
- 不能同一列
on_path记录该列是否已选。
- 不能同一斜线上
x + y或x - y相等时,两点在同一条线上,记录这两是否已选即可。diag1记录x + y。diag2记录x - y。
问题转换成多个子问题:
- 原问题:选n个皇后。
- 子问题:在第
row行选一个皇后。
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> ans;
vector<int> cols(n), on_path(n), diag1(n * 2 - 1), diag2(n * 2 - 1);
function<void(int)> dfs = [&](int row) {
if(row >= n) {
vector<string> t(n);
for (int i = 0; i < n; ++i) //".Q.."
t[i] = string(cols[i], '.') + 'Q' + string(n - cols[i] - 1, '.');
ans.emplace_back(t);
return;
}
for (int col = 0; col < n; ++col) { //枚举列
int rc = row - col + n - 1; // +n-1 变回正数
if(on_path[col] || diag1[row + col] || diag2[rc]) continue; //该列已选 或 在一条斜线上
cols[row] = col;
on_path[col] = diag1[row + col] = diag2[rc] = true;
dfs(row + 1); //这一行选完了,下一行
on_path[col] = diag1[row + col] = diag2[rc] = false; //恢复
}
};
dfs(0);
return ans;
}
};