BFS
最短单词路径(输出所有路径)
把对节点的BFS转换为对路径的DFS,依然可以用层次遍历的思路解决,有两点需要注意
- 从队列的pop出一个路径时需要把它的长度和最短路径长度做比较
- 对visited节点的更新需要在整个层次遍历完之后进行
class Solution {
public:
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
queue<vector<string>> q;
vector<vector<string>> ans;
unordered_set<string> wordSet;
unordered_set<string> visitedSet;
for(string word: wordList)
wordSet.insert(word);
q.push({beginWord});
int shortest = 1005;
while(!q.empty()){
vector<string> visited;
int size = q.size();
while(size--){
vector<string> curr = q.front();
q.pop();
if(curr.back() == endWord){
if(curr.size() < shortest){
for(int i = 0;i < ans.size(); i++)
ans[i].clear();
ans.clear();
ans.push_back(curr);
shortest = curr.size();
}
else if(curr.size() == shortest){
ans.push_back(curr);
}
}
if(curr.size() > shortest)
continue;
string last = curr.back();
for(int i = 0;i < last.size(); i++){
string tmp = last;
for(char c: "abcdefghijklmnopqrstuvwxyz"){
tmp[i] = c;
if(c != last[i] && wordSet.find(tmp) != wordSet.end() && (visitedSet.find(tmp) == visitedSet.end() || tmp == endWord)){
vector<string> curr_tmp = curr;
curr_tmp.push_back(tmp);
q.push(curr_tmp);
visited.push_back(tmp);
}
}
}
}
for(auto s: visited)
visitedSet.insert(s);
}
return ans;
}
};
到离得最近的0的距离
typedef pair<int,int> P;
class Solution {
public:
vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
int n = mat.size();
int m = mat[0].size();
queue<P> q;
vector<vector<int>> ans;
for(int i = 0;i < n; i++){
vector<int> tmp(m, 99999);
ans.push_back(tmp);
}
for(int i = 0;i < n; i++){
for(int j = 0;j < m; j++){
if(mat[i][j] == 0){
ans[i][j] = 0;
q.push({i,j});
}
}
}
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
while(!q.empty()){
P u = q.front();
q.pop();
int x = u.first, y = u.second;
for(int i = 0;i < 4; i++){
int nx = x + dx[i];
int ny = y + dy[i];
if(nx >= 0 && nx < n && ny >= 0 && ny < m && ans[nx][ny] > ans[x][y] + 1){
ans[nx][ny] = ans[x][y] + 1;
q.push({nx, ny});
}
}
}
return ans;
}
};
DFS
查找最大的连通面积
class Solution {
public:
int m, n, curr;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
void dfs(vector<vector<int>>& grid, int x, int y){
grid[x][y] = 0;
curr += 1;
for(int i = 0;i < 4; i++){
int nx = x + dx[i];
int ny = y + dy[i];
if(nx >= 0 && nx < n && ny >= 0 && ny < m && grid[nx][ny] == 1){
dfs(grid, nx, ny);
}
}
}
int maxAreaOfIsland(vector<vector<int>>& grid) {
n = grid.size();
m = grid[0].size();
int ans = 0;
for(int i = 0;i < n; i++){
for(int j = 0;j < m; j++){
if(grid[i][j] == 1){
curr = 0;
dfs(grid, i, j);
if(curr > ans)
ans = curr;
}
}
}
return ans;
}
};
填充封闭区域
从边界上的“缺口”开始DFS,剩下没有遍历到的”缺口“就是被包围的。
class Solution {
public:
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
int n, m;
void dfs(vector<vector<char>>& board, int x, int y){
board[x][y] = 'Z';
for(int i = 0;i < 4; i++){
int nx = x + dx[i];
int ny = y + dy[i];
if(nx >= 0 && nx < n && ny >= 0 && ny < m && board[nx][ny] == 'O')
dfs(board, nx, ny);
}
}
void solve(vector<vector<char>>& board) {
n = board.size();
m = board[0].size();
for(int i = 0;i < n; i++){
if(board[i][0] == 'O')
dfs(board, i, 0);
if(board[i][m-1] == 'O')
dfs(board, i, m-1);
}
for(int i = 0;i < m; i++){
if(board[0][i] == 'O')
dfs(board, 0, i);
if(board[n-1][i] == 'O')
dfs(board, n-1, i);
}
for(int i = 0;i < n; i++){
for(int j = 0;j < m; j++){
if(board[i][j] == 'Z')
board[i][j] = 'O';
else if(board[i][j] == 'O')
board[i][j] = 'X';
}
}
}
};
括号生成
三种方法
- 动态规划法:求解包含n对括号的字符串时,如果包好0到n-1对括号的解都知道,那就可以直接得到n对括号的解。设想n对括号的解集包括两部分,一部分是可以拆为两部分的,就是左边是完整的k对括号,右边是完整的n-k对括号,另一部分是不可以拆分的,也就是最外层有一对括号,括号里面是n-1对括号。为了避免生成过程中产生重复,所以用set记录生成的所有括号。
- 暴力法:这道题一开始想到的就是动态规划法,后来才知道可以DFS,直接写DFS感觉优点理解不了,所以就实现了下暴力法方便自己理解。暴力法就是生成有左右括号组成的长度为2n的字符串,然后再挑选其中的合法字符串。合法的定义就是:
( 的数量要一直大于等于) 的数量,并且遍历完成后左右括号的数量相等且都为n。 - DFS:在搜索的过程中就判断是否合法,left,right变量记录已经用掉的左右括号数量,left==0 && right == 0表明用完了则curr就是答案,否则只有在left<=right的时候也就是用掉的左括号多于右括号的时候才继续后续的添加。
class Solution {
public:
vector<string> generateParenthesis_dp(int n)
{
unordered_set<string> ans[n+1];
for(int i = 1;i <= n; i++)
{
if(i == 1)
ans[i].insert("()");
else{
for(auto it : ans[i-1])
ans[i].insert("("+it+")");
for(int j = 1;j <= i-1; j++){
for(auto& it1 : ans[j]){
for(auto& it2 : ans[i-j])
ans[i].insert(it1+it2);
}
}
}
}
vector<string> ans_v;
for(auto it : ans[n])
ans_v.push_back(it);
return ans_v;
}
vector<string> generateParenthesis_BruteForce(int n){
vector<string> all, ans;
dfs_BruteForce("", n * 2, all);
cout << all.size() << endl;
for(int i = 0;i < all.size(); i++){
if(valid(all[i]))
ans.push_back(all[i]);
}
return ans;
}
void dfs_BruteForce(string curr, int k, vector<string>& all){
if(k == 1){
all.push_back(curr+"(");
all.push_back(curr+")");
}
else{
dfs_BruteForce(curr+"(", k-1, all);
dfs_BruteForce(curr+")", k-1, all);
}
}
bool valid(string& s){
int left = 0, right = 0;
for(int i = 0;i < s.size(); i++){
if(s[i] == '(')
left += 1;
else if(s[i] == ')')
right += 1;
if(left < right)
return false;
}
return left == right && left == s.size() / 2;
}
vector<string> generateParenthesis(int n){
vector<string> ans;
dfs("", n, n, ans);
return ans;
}
void dfs(string curr, int left, int right, vector<string>& ans){
if(left == 0 && right == 0)
ans.push_back(curr);
if(left <= right && right > 0)
dfs(curr + ")", left, right-1, ans);
if(left <= right && left > 0)
dfs(curr + "(", left-1, right, ans);
}
};
|