题目:矩阵单词搜索

难度:Medium

题目内容

Given a 2D board and a word, find if the word exists in the grid.

The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.

翻译

给定一个2D的字符数组和一个单词,找出这个词是否存在于网格中。

这个词可以用顺序相邻的细胞的字母来构造,在那里“相邻”的细胞是水平的或垂直的相邻的。同一个字母单元可能不止一次使用。

Example:

board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
] Given word = "ABCCED", return true.
Given word = "SEE", return true.
Given word = "ABCB", return false.

我的思路:对整个二维数组进行循环,对于每一个字母都进入递归方法,

1、判断当前字符如果不与传入字符串第一个字母匹配,或者访问过则返回fasle;

2、这是最后一个字符,返回true;(已经通过上面的判断已经是匹配的)

3、将此位置的访问符置1,然后分别向上、下、左、右四个方向调用递归方法;

4、四个方向访问完毕,说明由此处开始的路径已经有结果,将此位置访问符再置0,并返回四个方向的“或”。

为什么又要再置0?

  因为整个递归过程就只有一个used访问标志矩阵(引用类型),如果每次访问后就设置1,不再管,那么之前已经失败的路径就会对之后再访问的路径(对于此路径是新访问的)产生影响。

此处的访问符类 used 似于第[47]题Permutations 2  中的used使用方法是一样的,不过意义不同,

所以,若在递归中有包含访问符,调用递归结束后,访问符应该置0(或false)

我的代码:

     public boolean exist(char[][] board, String word) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (find(word, i, j, board, new int[board.length][board[0].length])) {
return true;
}
}
}
return false;
} private boolean find(String word, int i, int j, char[][] board, int[][] used) {
if (i < 0 || i > board.length-1 || j < 0 || j > board[0].length-1) {
return false;
}
if (board[i][j] != word.charAt(0) || used[i][j] == 1) {
return false;
} else if (word.length() == 1) {
return true;
}
used[i][j] = 1;
boolean ans = find(word.substring(1), i-1, j, board, used)
|| find(word.substring(1), i+1, j, board, used)
|| find(word.substring(1), i, j-1, board, used)
|| find(word.substring(1), i, j+1, board, used);
used[i][j] = 0;
return ans;
}

我的复杂度:O((m*n)2

编码过程中的问题

1、之前采用的是先判断首字母是匹配然后直接返回find方法的结果,后来发现这样做是不行的,因为如果在正确答案的前面如果有一个是前面匹配后面不匹配的错误答案,就会直接返回错误答案的false;——————如果  true  则return true,否则继续

2、之前没考虑到标志位,从而路径会往回找;“【【a,a】】”  “aaa”

3、之前是用了四个标志位“up-down-left-right”,每次都判断是否能上下左右再进行递归调用,如下:

        if (i > 0) {
up = find(word.substring(1), i-1, j, board, used);
}

  然后最后再对这四个标志位进行 或 运算,但是这样做路径中的字母每次都会进行四个递归,没有短路的可能,所以当需要方法多分支递归的时候,最好改成直接调用方法进行  短路与或   运算, 然后在方法的开头加入此结果的判断,这样能减少不少多余的运算。【本题将是否能上下左右的判断加入到了递归方法的最开始】

4、本方法其实还可以优化,就是将访问过的字符用“*”表示,在递归结束后再设置成原来的值,这样就可以省去新建一个标志矩阵。

答案代码

 public boolean exist(char[][] board, String word) {
char[] w = word.toCharArray();
for (int y=0; y<board.length; y++) {
for (int x=0; x<board[y].length; x++) {
if (exist(board, y, x, w, 0)) return true;
}
}
return false;
} private boolean exist(char[][] board, int y, int x, char[] word, int i) {
if (i == word.length) return true;
if (y<0 || x<0 || y == board.length || x == board[y].length) return false;
if (board[y][x] != word[i]) return false;
board[y][x] ^= 256;
boolean exist = exist(board, y, x+1, word, i+1)
|| exist(board, y, x-1, word, i+1)
|| exist(board, y+1, x, word, i+1)
|| exist(board, y-1, x, word, i+1);
board[y][x] ^= 256;
return exist;
}

答案思路

基本思路是一样的,不过有两个亮点是比我的方法好的:

1、利用char[] 和 一个 int 表示当前所在第几个字母,代替了频繁利用subString来新建一个字符串;

2、利用二进制运算  与或  的特性——与或全1,再与或全1就会等于自己,因为说好都是字母,而且字母为65~90,95~122内,所以与或128也是可以的。从而不必再用temp了。

LeetCode第[79]题(Java):Word Search(矩阵单词搜索)的更多相关文章

  1. 【LeetCode每天一题】Word Search(搜索单词)

    Given a 2D board and a word, find if the word exists in the grid.The word can be constructed from le ...

  2. LeetCode 79. Word Search(单词搜索)

    Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from l ...

  3. LeetCode第[33]题(Java):Search in Rotated Sorted Array

    题目:在翻转有序中搜索 难度:Medium 题目内容: Suppose an array sorted in ascending order is rotated at some pivot unkn ...

  4. LeetCode第[34]题(Java):Search for a Range

    题目:搜索目标范围 难度:Medium 题目内容: Given an array of integers nums sorted in ascending order, find the starti ...

  5. LeetCode第[18]题(Java):4Sum 标签:Array

    题目难度:Medium 题目: Given an array S of n integers, are there elements a, b, c, and d in S such that a + ...

  6. LeetCode第[1]题(Java):Two Sum 标签:Array

    题目: Given an array of integers, return indices of the two numbers such that they add up to a specifi ...

  7. LeetCode第[46]题(Java):Permutations(求所有全排列) 含扩展——第[47]题Permutations 2

    题目:求所有全排列 难度:Medium 题目内容: Given a collection of distinct integers, return all possible permutations. ...

  8. LeetCode第[1]题(Java):Two Sum (俩数和为目标数的下标)——EASY

    题目: Given an array of integers, return indices of the two numbers such that they add up to a specifi ...

  9. 【LeetCode-面试算法经典-Java实现】【079-Word Search(单词搜索)】

    [079-Word Search(单词搜索)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a 2D board and a word, find if ...

随机推荐

  1. IIS7.5 错误代码0x8007007e HTTP 错误 500.19

    目录 问题案例 解决问题 参考资料 问题案例 今天在win2008+IIS7.5的环境中部署WCF服务后,一直出现无法打开的页面.具体错误信息如下: HTTP 错误 500.19 - Internal ...

  2. 将 ssh (security shell) 移植到 vxworks

    openssh 依赖 openssl,这两个东西主要针对posix系统,移植到 vxworks 等实时系统有相当的难度. 可以考虑移植如下的库(ssh server): dropbear: https ...

  3. HDU3123:GCC(同余模简单题)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3123 题意很简单,就是同余模的简单应用. 代码如下: #include <iostream> ...

  4. 记录:python读取excel文件

    由于最近老是用到python读取excel文件,所以特意记录一下python读取excel文件的大体框架. 库:xlrd(读),直接pip安装即可.想要写excel文件的话,安装xlwd库即可,也是直 ...

  5. windows安装redis, php5.5

    全套安装包地址 http://download.csdn.net/detail/whellote/9572797   解压 redis-2.2.5-win32-win64, 将里面的内容拷贝到j:/r ...

  6. TOSCA自动化测试工具--Log defect

    1.执行完用例后,对于失败的用例进行分析,如果有缺陷,可以提对应的缺陷 2.在issues模块, 右键创建自己需要的文件夹,然后在文件夹上右键找到虫子图形点下,就可以创建缺陷了,填上对应的内容 3.如 ...

  7. windows上使用clang编译程序

    环境:windows7,64位 1.下载并安装llvm,安装包里除了llvm,也有clang: http://releases.llvm.org/5.0.0/LLVM-5.0.0-win64.exe ...

  8. 查看ubuntu 各系统的内核版本

    1.查看ubuntu版本号:   cat  /etc/issue 返回结果: Ubuntu 16.04.2 LTS \n \l   2.查看内核版本号:   cat /proc/version 返回结 ...

  9. Java:延迟功能的Robot在Lunix系统上会报错

    Java:延迟功能的Robot在Lunix系统上会报错 关于延迟功能的Robot: 今天开发过程中发现,本机开发好的项目,部署到Lunix服务器竟然报错!查了代码发现: Robot r = new R ...

  10. Eclipse安装Activiti插件(流程设计器)

    Eclipse安装Activiti插件(流程设计器) 一.安装步骤: 1,打开Eclipse的 Help -> Install New Software,填上插件地址: Name:Activit ...