之前收藏了极客时间的算法训练营3期 共21课,计划每一课写博客来记录学习,主要形式为
方法类型1
题1
题解
题2
题解
方法类型2
题1
题解
……
题目大体来自leetcode 和 acwing
主要记录和理解代码,所以基本完全搬运了视频题解代码,
个人学习感受体现在大致思路的总结和注释上。
一、深度优先搜索
第一题
找到控制皇后位置的量
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
this->n = n;
used = vector<bool>(n, false);
vector<vector<string>> result;
dfs(0);
for (vector<int>& an : ans) {
vector<string> pattern(n,string(n, '.'));
for(int i = 0; i < n; i++) {
pattern[i][an[i]] = 'Q';
}
result.push_back(pattern);
}
return result;
}
private:
int n;
vector<vector<int>> ans;
vector<int> p;
unordered_map<int, bool> usedPlus;
unordered_map<int, bool> usedMinus;
vector<bool> used;
void dfs(int row) {
if (row == n) {
ans.push_back(p);
}
/*有4个量控制到皇后选择
横行 :行号在递归
竖行 : used 数组
\ :row - col
/ :row + col
*/
for (int col = 0; col < n; col++) {
if(!used[col] && !usedPlus[row + col] && !usedMinus[row - col]) {
p.push_back(col);
used[col] = true;
usedPlus[row + col] = true;
usedMinus[row - col] = true;
dfs(row + 1);
used[col] = false;
usedPlus[row + col] = false;
usedMinus[row - col] = false;
p.pop_back();
}
}
}
};
第二题
把字母组合存起来查表,深度优先即可.
class Solution {
public:
vector<string> letterCombinations(string digits) {
if (digits == "") return {};
this->digits = digits;
alphabet['2'] = "abc";
alphabet['3'] = "def";
alphabet['4'] = "ghi";
alphabet['5'] = "jkl";
alphabet['6'] = "mno";
alphabet['7'] = "pqrs";
alphabet['8'] = "tuv";
alphabet['9'] = "wxyz";
dfs(0);
return ans;
}
private:
unordered_map<char, string> alphabet;
string digits;
vector<string> ans;
string tmp;
void dfs(int index) {
if (index == digits.length()) {
ans.push_back(tmp);
return;
}
for (int i = 0; i < alphabet[digits[index]].length(); i++) {
tmp += alphabet[digits[index]][i];
dfs(index + 1);
tmp = tmp.substr(0, tmp.length() - 1);
}
}
};
二、广度优先搜索
第一题
1.岛屿数量
每个岛屿扩散开去。
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
this->grid = grid;
int count = 0;
m = grid.size();
n = grid[0].size();
visited = vector<vector<bool>>(m, vector<bool>(n, false));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (!visited[i][j] && (grid[i][j] == '1')) {
count++;
bfs(i, j);
}
}
}
return count;
}
private:
vector<vector<bool>> visited;
int m, n;
vector<vector<char>> grid;
void bfs(int x, int y) {
queue<pair<int, int>> q;
q.push({x, y});
int dx[] = {-1, 0, 0, 1};
int dy[] = {0, -1, 1, 0};
while (!q.empty()) {
int x = q.front().first;
int y = q.front().second;
q.pop();
visited[x][y] = true;
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || ny < 0 || nx >= m || ny >= n) continue;
if (visited[nx][ny]) continue;
if (grid[nx][ny] != '1')continue;
q.push({nx, ny});
visited[nx][ny] = true;
}
}
}
/*
void bfs (int i, int j) {
visited[i][j] = true;
if ((i + 1 < m) && (grid[i + 1][j] == '1') && !visited[i + 1][j]) {
bfs(i + 1, j);
}
if ((j + 1 < n) && (grid[i][j + 1] == '1') && !visited[i][j + 1]) {
bfs(i, j + 1);
}
if ((i - 1 >= 0) && (grid[i - 1][j] == '1') && !visited[i - 1][j]) {
bfs(i - 1, j);
}
if ((j - 1 >= 0) && (grid[i][j - 1] == '1') && !visited[i][j - 1]) {
bfs(i, j - 1);
}
return ;
}
*/
};
2.最小基因变化
第二题
bfs可以着重使用层数来标记数据
class Solution {
public:
int minMutation(string start, string end, vector<string>& bank) {
for (string banks : bank) {
hashMap.insert(banks);
}
const char gene[] = {'A', 'T', 'C', 'G'};
queue<string> q;
q.push(start);
while (!q.empty()) {
string str = q.front();
q.pop();
for (int i = 0; i < 8; i++)
for (int j = 0; j < 4; j++) {
if (str[i] != gene[j]) {
string ns = str;
ns[i] = gene[j];
if (hashMap.find(ns) == hashMap.end()) continue;
if (depth.find(ns) != depth.end()) continue;
depth[ns] = depth[str] + 1;
if (ns == end) return depth[ns];
q.push(ns);
}
}
}
return -1;
}
private:
unordered_set<string> hashMap;
unordered_map<string, int> depth;
};
第三题
①bfs
拓扑排序。构建了出边数组,入度数组,当入度降至0时执行入队,类似上次的课程表
class Solution {
public:
int longestIncreasingPath(vector<vector<int>>& matrix) {
m = matrix.size();
n = matrix[0].size();
to = vector<vector<int>>(m * n);
indeg = vector<int>(m * n, 0);
dist = vector<int>(m * n, 0);
const int dx[] = {-1, 0, 0, 1};
const int dy[] = {0, -1, 1, 0};
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < 4; k++) {
int ni = i + dx[k];
int nj = j + dy[k];
if (valid(ni, nj) && matrix[ni][nj] > matrix[i][j]) {
addEdge(num(i, j), num(ni, nj));
}
}
queue<int> q;
for (int i = 0; i < m * n; i++) {
if (indeg[i] == 0) {
q.push(i);
dist[i] = 1;
}
}
while (!q.empty()) {
int x = q.front();
q.pop();
for (int y : to[x]) {
indeg[y]--;
dist[y] = max(dist[y], dist[x] + 1);
if (indeg[y] == 0) {
q.push(y);
}
}
}
int ans = 1;
for (int dis : dist) {
ans = max(ans, dis);
}
return ans;
}
private:
int m, n;
vector<int> indeg;
vector<int> dist;
vector<vector<int>> to;
void addEdge (int u, int v) {
indeg[v]++;
to[u].push_back(v);
}
int num(int i, int j) {
return i * n + j;
}
bool valid(int i, int j) {
return i < m && j < n && i >= 0 && j >= 0;
}
};
②dfs,记忆化搜索
class Solution {
public:
int longestIncreasingPath(vector<vector<int>>& matrix) {
this->matrix = matrix;
m = matrix.size();
n = matrix[0].size();
dist = vector<vector<int>>(m, vector<int>(n, -1));
int ans = 1;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
ans = max(ans, dfs(i, j));
}
return ans;
}
private:
int m, n;
vector<vector<int>> dist;
vector<vector<int>> matrix;
int dfs(int x, int y) {
if (dist[x][y] != -1) return dist[x][y];
dist[x][y] = 1;
const int dx[] = {-1, 0, 0, 1};
const int dy[] = {0, -1, 1, 0};
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (valid(nx, ny) && matrix[nx][ny] > matrix[x][y]) {
dist[x][y] = max(dist[x][y], dfs(nx, ny) + 1);
}
}
return dist[x][y];
}
bool valid(int i, int j) {
return i < m && j < n && i >= 0 && j >= 0;
}
};