题目:
给定一个二维数组,可以看做其中的1被0包围,求数组中有几堆1?
Code:
class Test{
public static void main(String[] args){
int[][] matrix = {
{1, 1, 0, 1},
{0, 1, 1, 0},
{0, 0, 0, 1},
{0, 1, 1, 1}
};
int m = matrix.length, n = matrix[0].length;
//bfs方法:
// int[][] dir = {
// {0, 1},
// {1, 0},
// {0, -1},
// {-1, 0}
// };
// int res = 0;
// Queue<Position> q = new LinkedList<Position>();
// for(int i=0; i<m; i++){
// for(int j=0; j<n; j++){
// if(matrix[i][j] == 1){
// res++;
// Position pos = new Position(i, j);
// q.add(pos);
// while(!q.isEmpty()){
// Position x = q.poll();
// matrix[x.r][x.c] = 2;
// for(int k=0; k<dir.length; k++){
// int r = x.r + dir[k][0];
// int c = x.c + dir[k][1];
// if(r>=0 && r<m && c>=0 && c<n && matrix[r][c]==1){
// Position tmp = new Position(r, c);
// q.add(tmp);
// }
// }
// }
// }
// }
// }
// System.out.println(res);
//dfs方法:
Solution sol = new Solution();
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
if(matrix[i][j] == 1){
sol.res++;
sol.dfs(matrix, i, j);
}
}
}
System.out.println(sol.res);
}
}
class Solution{
int res;
Solution(){
res = 0;
}
public void dfs(int[][] matrix, int row, int col){
int m = matrix.length, n = matrix[0].length;
int[][] dir = {
{0, 1},
{1, 0},
{0, -1},
{-1, 0}
};
matrix[row][col] = 2;
for(int i=0; i<dir.length; i++){
int r = row + dir[i][0];
int c = col + dir[i][1];
if(r>=0 && r<m && c>=0 && c<n && matrix[r][c]==1){
dfs(matrix, r, c);
}
}
}
}
class Position{
int r, c;
Position(int r, int c){
this.r = r;
this.c = c;
}
}
小结:
这里BFS和DFS的Runtime应该都是O(4mn),如果不对请纠正,space是O(mn),一个用了递归(DFS),一个由于Queue的存在是顺序的,但是两者除了便利方式外,其实原理、运行方式都非常接近。
DFS之所以使用递归,因为内存本身就是一个Stack,我们只是加以利用罢了。换句话说,如果我们像BFS那样,手动建立一个Stack,也可以完成顺序的DFS。
下面这个图的DFS和BFS的例子是个很好的印证:
public void bfs(){
Queue<Integer> q = new Queue<Integer>();
q.enque(0);
display(0);
list[0].wasVisited = true;
while(!q.isEmpty()){
int x1 = q.deque();
int x2;
while((x2 = getAdjUnvisited(x1)) != -1){
q.enque(x2);
display(x2);
list[x2].wasVisited = true;
}
}
for(int i=0; i<cnt; i++)
list[i].wasVisited = false;
}
public void dfs(){
Stack<Integer> s= new Stack<Integer>();
s.push(0);
display(0);
list[0].wasVisited = true;
while(!s.isEmpty()){
int x = getAdjUnvisited(s.peek());
if(x != -1){
s.push(x);
display(x);
list[x].wasVisited = true;
}
else
s.pop();
}
for(int i=0; i<cnt; i++)
list[i].wasVisited = false;
}