79. 单词搜索

本文介绍如何利用动态规划解决LeetCode上的单词搜索问题。在给定的二维网格中,按照字母顺序寻找目标单词,允许水平或垂直相邻单元格构成单词,但不能重复使用同一单元格。通过比较word和board的字符,使用布尔数组记录已使用位置,进行回溯和移动判断,直至找到完整匹配或遍历完所有可能。

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例:

board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]

给定 word = “ABCCED”, 返回 true.
给定 word = “SEE”, 返回 true.
给定 word = “ABCB”, 返回 false.

方法:动态规划
思路:拿着word当前位置的字符,和board数组的元素比较,如果相等,则判断word下个字符是否和board当前元素的左右上下邻近位置是否相等,相等则继续上述操作,并使用布尔数组记录board元素对应位置元素是否已被使用过;
1,从board的开始位置和word的第一个字符进行比较判断,若相等则继续word下个字符判断 ,并且将当前位置对应布尔数组置为false;
2,当word字符出现和board中不连续匹配时,则将其进行回溯,回溯过程中要将布尔数组中该位置回溯为可用,也就是置为true;并且将board的位置进行移动,从word头字符开始下一轮判断;
3,直到出现两种结果。一,出现将word字符全部匹配完成的情况,则直接返回true即可;二,将board全部尝试完成,也没用和word匹配的结果,则返回false;
4,注意,board数组和word特殊情况的判断;

class Solution {
    int col;
    int row;
    public boolean exist(char[][] board, String word) {
        //特殊情况
        if (board == null || word == null || word.isEmpty())
            return false;
        //col记录数组行,row记录数组列,len记录单词长度
        col = board.length;
        row = board[0].length;
        int len = word.length();
        //特殊情况
        if (col * row < len)
            return false;
        char[] warr = word.toCharArray();
        //需要一个数组记录当前位置是否被使用过
        boolean[][] flag = new boolean[col][row];
        //开始遍历数组board并且判断是否存在word
        for (int i = 0; i < col; i ++) {
            for (int j = 0; j < row; j ++) {
                if (find(board,i,j,0,warr,flag))//找齐了Word字符
                    return true;
            }
        }
        return false;
    }
    
    //动态规划,index表示单词的第几个字符,也就是warr的索引
    private boolean find(char[][] board, int x, int y, int index, char[] warr, boolean[][] flag) {
        //word全部找完,则为true
        if (index == warr.length)
            return true;
        //边界溢出,或者board当前坐标和Word当前字符不相同
        if (x < 0 || x >= col || y < 0 || y >= row || board[x][y] != warr[index])
            return false;
        //否则肯定相同,则继续下一个字符的判断
        if (!flag[x][y]) {//当前字符不能被使用
            flag[x][y] = true;//使用当前字符
            if (find(board,x-1,y,index+1,warr,flag) || find(board,x,y-1,index+1,warr,flag) || 
                find(board,x+1,y,index+1,warr,flag) || find(board,x,y+1,index+1,warr,flag)) //上下左右递归判断
                return true;
            //下个字符不符合,所以回溯当前字符到没被使用
            flag[x][y] = false;
        }
        //下个字符不相同
        return false;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值