被围绕的区域的思路探讨与源码
被围绕的区域的题目如下图,该题属于数组和搜索类型的题目,主要考察对于搜索方法的使用和二维数组遍历方法的理解。本文的题目作者想到2种方法,分别是BFS广度优先搜索方法和DFS深度优先搜索方法,其中BFS广度优先搜索方法使用Java进行编写,而DFS深度优先搜索方法使用Python进行编写,当然这可能不是最优的解法,还希望各位大佬给出更快的算法。
本人认为该题目可以使用BFS广度优先搜索方法进行解决,首先构造一个记录位置的类,类的内部元素有横坐标和纵坐标。开始先对数组进行判断,如果是空或者数组长度为0就直接结束程序。然后计算数组的长度和宽度,开始从左上角的位置进行遍历,寻找边缘里第一个是‘O’的元素开始进行搜索。在搜索函数内部,主要是初始化一个队列,然后用去搜索当前元素的上下左右是否有元素等于‘O’,如果有就把它赋值为’#'然后把这个元素的位置记录下来并加入到队列,方便后续继续搜索,直到最终的队列为空就返回。最后再次遍历数组将原来的‘O’转换为‘X’,再把‘#’转换为’O’后,得到最终的数组就是结果。那么按照这个思路我们的Java代码如下:
#喷火龙与水箭龟
class Solution {
public class Locate{
int ir;
int jr;
Locate(int ir, int jr) {
this.ir = ir;
this.jr = jr;
}
}
public void solve(char[][] board) {
if (board == null || board.length == 0){
return;
}
int rowNum = board.length;
int colNum = board[0].length;
for (int ib = 0; ib < rowNum; ib++) {
for (int jb = 0; jb < colNum; jb++) {
boolean borderFlag = (ib == 0 || jb == 0) || (ib == rowNum - 1 || jb == colNum - 1);
if (board[ib][jb] == 'O' && borderFlag) {
searchBFS(board,ib,jb);
}
}
}
for (int ir = 0; ir < rowNum; ir++) {
for (int jr = 0; jr < colNum; jr++) {
if (board[ir][jr] == 'O') {
board[ir][jr] = 'X';
}
if (board[ir][jr] == '#') {
board[ir][jr] = 'O';
}
}
}
}
public void searchBFS(char[][] board,int ir,int jr) {
Queue<Locate> queueList = new LinkedList<>();
queueList.add(new Locate(ir, jr));
board[ir][jr] = '#';
while (! queueList.isEmpty()) {
Locate nowValue = queueList.poll();
if (nowValue.ir - 1 >= 0 && board[nowValue.ir - 1][nowValue.jr] == 'O') {
queueList.add(new Locate(nowValue.ir - 1, nowValue.jr));
board[nowValue.ir - 1][nowValue.jr] = '#';
}
if (nowValue.ir + 1 <= board.length - 1 && board[nowValue.ir + 1][nowValue.jr] == 'O') {
queueList.add(new Locate(nowValue.ir + 1, nowValue.jr));
board[nowValue.ir + 1][nowValue.jr] = '#';
}
if (nowValue.jr - 1 >= 0 && board[nowValue.ir][nowValue.jr - 1] == 'O') {
queueList.add(new Locate(nowValue.ir, nowValue.jr - 1));
board[nowValue.ir][nowValue.jr - 1] = '#';
}
if (nowValue.jr + 1 <= board[0].length - 1 && board[nowValue.ir][nowValue.jr + 1] == 'O') {
queueList.add(new Locate(nowValue.ir, nowValue.jr + 1));
board[nowValue.ir][nowValue.jr + 1] = '#';
}
}
}
}
显然,我们看到BFS广度优先搜索的方法的效果一般,同时还可以使用DFS深度优先搜索的方法。首先判断数组是否为空,如果是则直接结束;计算二维数组的长度和宽度,并且对长和宽进行判断,如果小于3就直接返回,然后开始按照行的边界出发去遍历搜索,在深度优先搜索函数内部是判断边界是否溢出或者当前元素是否不等于’O’,如果是就结束搜索,否则就将当前元素的值替换为’#'后,再次获取当前元素的上下左右的元素进行深度优先搜索。在按照行的边界出发搜索完毕后,进行列的边界作为出发点再次搜索。最后将得到的搜索结果里面的‘O’转换为‘X’,把‘#’转换为’O’后,得到最终的数组就是我们需要的结果。所以按照这个思路就可以解决,下面是Python代码部分:
#喷火龙与水箭龟
class Solution:
def solve(self, board: List[List[str]]) -> None:
if(not board):
return
rowLen = len(board)
colLen = len(board[0])
if(rowLen < 3 or colLen < 3):
return
def searchDFS(ir,jr):
if(ir < 0 or jr < 0 or ir >= rowLen or jr >= colLen or board[ir][jr] != 'O'):
return
board[ir][jr] = '#'
searchDFS(ir-1,jr)
searchDFS(ir+1,jr)
searchDFS(ir,jr-1)
searchDFS(ir,jr+1)
for ir in range(rowLen):
searchDFS(ir,0)
searchDFS(ir,colLen-1)
for jr in range(colLen):
searchDFS(0,jr)
searchDFS(rowLen-1,jr)
for ir in range(rowLen):
for jr in range(colLen):
if(board[ir][jr]=='O'):
board[ir][jr]='X'
if(board[ir][jr]=='#'):
board[ir][jr]='O'
从结果来说Java版本的BFS广度优先搜索方法的效率比较一般,而Python版本的DFS深度优先搜索方法的速度还可以,但应该是有更多的方法可以进一步提速的,希望朋友们能够多多指教,非常感谢。