【DFS深度优先遍历】 字母表问题

数据结构与算法


题目类型描述: 给出一个二维的字母板和一个单词,寻找字母板网格中是否存在这个单词(单词可以由按顺序的相邻单元的字母组成,其中相邻单元指的是水平或者垂直方向相邻。每个单元中的字母最多只能使用一次)。

具象理解

       假设有这样一个二维字母表(如图)和单词“ABCCED”:
【DFS深度优先遍历】 字母表问题_第1张图片
有如下路径存在:
【DFS深度优先遍历】 字母表问题_第2张图片
我们应该返回“true”。

抽象建模

       可以根据题给的二维字母表构建这样的二维boolean型数组,通过查找上下左右四个方向的字母,深度遍历。
       不过我们需要清楚一点,我们在遍历的时候往往在做重复工作(检验上下左右四个字母是否符合要求),而且逐层深入,故考虑递归,将大问题划分为一个个小问题解决。分析时我们发现每个“小问题”都包含这两个操作:

  1. 检验当前字母是否符合要求。
  2. 检验它的相邻字母是否也符合要求(如果不符合的话即便该字母正确,依然没用,该返回false的结果)。

代码如下:

package lint_code5;

public class Solution123 {
	
	public static void main(String args[]){
		char[][] board=new char[3][4];
		board[0]="ABCE".toCharArray();
		board[1]="SFCS".toCharArray();
		board[2]="ADEE".toCharArray();
		print(board);//构建字母表
		System.out.println(exist(board, "ABCCED"));
	}

    public static boolean exist(char[][] board, String word) {//功能函数
        // 排除特殊情况
    	if(board.length==0||word.length()==0||board==null||word=="") return false;
    	//构建同等的真值表
    	boolean[][] check=new boolean[board.length][board[0].length];
    	
    	for(int i=0;i<board.length;i++)
    		for(int j=0;j<board[0].length;j++)//双循环表示字母表的每个位置都要检查(不过有的地方因为第一个字母就不符合,所以很快舍弃,不太耽误运行时间)
    			if(DFS(board, check, word, i, j, 0))
    				return true;
    	
    	return false;
    }
    
    public static boolean DFS(char[][] b, boolean[][] c, String word, int i, int j, int wordIndex){//wordIndex:表示当前单词的检索位置
    	
    	if(wordIndex>=word.length()) return true;
    	if(i>=c.length||j>=b[0].length||i<0||j<0) return false;
    	if(c[i][j]) return false;
    	
    	if(b[i][j]!=word.charAt(wordIndex)) return false;
    	c[i][j]=true;
    	//递归
    	if(DFS(b, c, word, i+1, j, wordIndex+1)) return true;
    	if(DFS(b, c, word, i-1, j, wordIndex+1)) return true;
    	if(DFS(b, c, word, i, j+1, wordIndex+1)) return true;
    	if(DFS(b, c, word, i, j-1, wordIndex+1)) return true;
    	//回溯
    	c[i][j]=false;//如果它相邻位置字母仍不符合要求,应该归还该位置为false,
    	return false;
    }
    
    
    //print检验
    public static void print(char[][] c){
    	for(int i=0;i<c.length;i++){
    		for(int j=0;j<c[0].length;j++)
    			System.out.print(c[i][j]+", ");
    		System.out.println();
    	}
    }
    
    public static void print(boolean[][] c){
    	for(int i=0;i<c.length;i++){
    		for(int j=0;j<c[0].length;j++)
    			System.out.print(c[i][j]+", ");
    		System.out.println();
    	}
    }
}

总结

       DFS(深度优先遍历)在思考方式上和DP(动态规划)问题感觉差别不大,核心都是递归,注意理解。

你可能感兴趣的:(数据结构与算法,Java,数据结构与算法)