所谓DFS,就是深度遍历,一般用到的就是递归。BFS一般就是广度遍历,一般就是利用辅助栈或者队列,来实现层次遍历。
130. Surrounded Regions
问题描述:
Given a 2D board containing 'X'
and 'O'
(the letter O), capture all regions surrounded by 'X'
.
A region is captured by flipping all 'O'
s into 'X'
s in that surrounded region.
For example,
X X X X X O O X X X O X X O X X
After running your function, the board should be:
X X X X X X X X X X X X X O X X
问题解析:
1. 此题的意思是:给定一个二维数组,将直接裸露在数组边界上面的o或者能通过上下左右四个位置的o到达边界的O不变,但是被x包围的O,必须改为X。
2. 这是典型的DFS使用。分别在上二维数组的四个最外边界上面寻找O,然后进一步通过上下左右四个位置扩展,遇到X就停止,这样就能找到所有不需要改变的O,然后将剩下的O变为X就行。这个过程就是深度遍历的过程。
3. 第一次通过深度遍历找出所有无需改变的O后,便于区分,将此O改为#号。遍历完成后,把二维数组中剩余的O就是需要变为X的O,改变即可,然后再讲二维数组中的#号改为O即可。
代码如下:
class Solution {
public:
// DFSSerach
void Srarch(vector<vector<char>>& board, int m, int n, int i, int j)
{
if(i<0 || i>m || j<0 || j>n)
return;
if(board[i][j] != 'O')
return;
board[i][j] = '#';
Srarch(board, m, n, i-1, j);
Srarch(board, m, n, i+1, j);
Srarch(board, m, n, i, j-1);
Srarch(board, m, n, i, j+1);
return;
}
void solve(vector<vector<char>>& board)
{
if(board.empty())
return;
int m = board.size();
int n = board[0].size();
// 上边缘和下边缘
for(int i=0; i<n; ++i)
{
if(board[0][i] == 'O')
{
Srarch(board, m-1, n-1, 0, i);
}
if(board[m-1][i] == 'O')
{
Srarch(board, m-1, n-1, m-1, i);
}
}
// 左边缘和有边缘
for(int i=0; i<m; ++i)
{
if(board[i][0] == 'O')
{
Srarch(board, m-1, n-1, i, 0);
}
if(board[i][n-1] == 'O')
{
Srarch(board, m-1, n-1, i, n-1);
}
}
// 将剩余的O变为X
for(int i=0; i<m; ++i)
{
for(int j=0; j<n; ++j)
{
if(board[i][j] == 'O')
board[i][j] = 'X';
}
}
//
for(int i=0; i<m; ++i)
{
for(int j=0; j<n; ++j)
{
if(board[i][j] == '#')
board[i][j] = 'O';
}
}
return;
}
};
127. Word Ladder---广度遍历
问题描述:
Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
- Only one letter can be changed at a time.
- Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog"
,
return its length 5
.
问题解析:
1.此题的意思是给定一个初始和末尾单词,利用字典中的单词集,从初始单词开始,每次变化单词中的一个字母,而且变化后的单词必须是字典集中的单词,求最少需要几步可以变为末尾单词。
2. 因为是求最小步数,其实这就是相当于一个数的层次遍历求最短层数。初始单词相当于根节点,其下层节点就是由初始单词变化一个字母并且出现在单词集中的单词。这样去想,求的是最小步数,所以,能由单词A直接转化为单词B的就没有必要通过中间单词C来转换成为单词B,所以当求出当前单词的所有下层节点后,就可以在单词集中删掉这些单词了。因为这些单词在以后必定不会出现,要不然求出的路径必不会是最短路径。
3. 此题既然可以转化为树,那么求树的最小叶节点层数,可以用递归DFS也可以用广度遍历BFS。DFS会超时,BFS成功AC。
代码如下:
class Solution {
public:
// BFS,宽度优先搜索
int ladderLength(string start, string end, vector<string>& wordList)
{
if (start.size() != end.size() || wordList.empty())
return 0;
if (start.empty() || end.empty())
return 0;
// 设置unordered_map,方便搜索,时间复杂度是1
unordered_set<string> dict(wordList.begin(), wordList.end());
// dis表示有几层,就是有多少个单词可以转化为end
int dis = 1;
// count表示当前弹出的节点个数,nodenum表示本层的节点个数
int count=0, nodenum=1;
// 设置辅助队列来模仿BFS,宽度优先搜索
deque<string> de;
de.push_back(start);
while(!de.empty())
{
string str(de.front());
de.pop_front();
++count;
for(int i=0; i<str.size(); ++i)
{
for(char j='a'; j<='z'; ++j)
{
char temp = str[i];
str[i] = j;
if(dict.count(str) > 0)
{
if(str == end)
{
++dis;
return dis;
}
de.push_back(str);
dict.erase(str);
}
str[i] = temp;
}
}
if(count == nodenum)
{
nodenum = de.size();
count = 0;
++dis;
}
}
return 0;
}
};