题目:矩阵单词搜索

难度: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. swagger多个分组代码展示

    /** * api信息 * * @param name 标题 * @param description 描述 * @param version 版本 * @return */ private ApiI ...

  2. MyEclipse 10的使用技巧

    默认快捷键 :Shift+Alt+s 然后选择generater getter and setter,这是快捷键.或者右键source里边有 generater getter and setter. ...

  3. Elasticsearch.js 发布 —— 在Node.js和浏览器中调用Elasticsearch(1)

    继PHP.Ruby.Python和Perl之后,Elasticsearch最近发布了Elasticsearch.js,Elasticsearch的JavaScript客户端库.可以在Node.js和浏 ...

  4. how to use greendao in android studio

    http://www.arjunsk.com/android/use-greendao-android-studio/ 1.新建一个java文件MainGenerator.java: import d ...

  5. python学习笔记(十八)网络编程之requests模块

    上篇博客中我们使用python自带的urllib模块去请求一个网站,或者接口,但是urllib模块太麻烦了,传参数的话,都得是bytes类型,返回数据也是bytes类型,还得解码,想直接把返回结果拿出 ...

  6. C的指针疑惑:C和指针8数组

    ]; ]; 上面申明两个数组,不能进行以下赋值 b = a; 你不能使用赋值符把一个数组的所有元素复制给另一个数组,必须使用一个循环,每次复制一个元素 数组和指针 ]; int *b; 声明一个数组, ...

  7. 详解MySQL第一篇—MySQL简要介绍及DDL语句

    背景:近几年,开源数据库逐渐流行起来.由于具有免费使用.配置简单.稳定性好.性能优良等优点,开源数据库在中低端应用上占据了很大的市场份额,而 MySQL 正是开源数据库中的杰出代表.MySQL 数据库 ...

  8. VMware+CentOS7+jdk1.7+hadoop2.4.1

    1.工具 CentOS7:去官网下载,然后找到阿里的镜像,DVD版本就好,4个G大小https://www.centos.org/download/ vmware:去官网下载最新版本 2.要点 先装V ...

  9. 什么是“HTML”?HTML的“标记”是什么?

    ①文本标记语言 即HTML(Hypertext Markup Language),是用于描述网页文档的一种标记语言. ②HTML 标记标签 通常被称为 HTML 标签 (HTML tag). ③HTM ...

  10. 基础知识总结之 jdk部分

    第一次安装jdk 按照操作走完  会出现 C:\Program Files\Java\jdk1.8.0_91 和 C:\Program Files\Java\jre1.8.0_91 两个目录 (平级目 ...