算法数据结构:深度优先搜索(DFS)

1,466 阅读1分钟

1、什么是深度优先搜索(DFS)

深度优先搜索用的是回溯思想,这种思想解决问题的过程,非常适合用递归来实现;换句话说,DFS 是借助栈来实现的。

举个栗子,假设你站在迷宫的某个岔路口,然后想找到出口。你随意选择一个岔路口来走,走着走着发现走不通的时候,你就回退到上一个岔路口,重新选择一条路继续走,直到最终找到出口。这种走法就是一种深度优先搜索策略。

2、代码模板

递归写法

visited = set()
def dfs(node, visited):
	if node in visited:
		return 
    visited.add(node)
    # process current node here
    process(node)
    for next_node in node.children(): 
    	if not next_node in visited:
        	dfs(next node, visited)

非递归写法

def dfs(self, tree):
	if tree.root is None:
    	return []
    visited, stack = [], tree.root
    
    while stack: 
    	node = stack.pop()
        visited.add(node)
        
        process(node)
        nodes = generate_related_nodes(node)
        stack.push(nodes)
        
	# other processing work
    ...

3、实战

3.1、统计封闭岛屿的数目

class Solution {

    private int[][] coords = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

    public int closedIsland(int[][] grid) {
        if (grid == null || grid.length < 3 || grid[0].length) {
            return 0;
        }
        
        int res = 0;

        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j <grid[0].length; j++) {
                if (grid[i][j] == 0 && dfs(grid, i, j)) {
                    res++;
                }
            }
        }
        return res;
    }

    public boolean dfs(int[][] grid, int i, int j) {
        // 当 i, j 超过数组 index 范围时,返回 false
        if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length) {
            return false;
        }

        // 遇到 1 说明被水域包围,返回 true
        if (grid[i][j] == 1) {
            return true;
        }
        
        // 将访问过得标记为 1,可以避免重复访问,计算的问题
        grid[i][j] = 1;

        boolean flag = true;

        // 校验四周是否都被水域包围,如果都被包围,则 flag 为 true
        for (int[] coord : coords) {
            flag = flag & dfs(grid, i + coord[0], j + coord[1]);
        }
        return flag;
    }
}

4、小结

DFS 通俗的理解就是,地毯式层层推进,从起始点开始,依次向外遍历。广度优先搜索和深度优先搜索是图上的两种最常用、最基本的搜索算法。