79、 Word Search (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.

For example,
Given board =

[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]
word  =  "ABCCED" , -> returns  true ,
word  =  "SEE" , -> returns  true ,

word = "ABCB", -> returns false.

题意就是说给一个二维char数组,找出一个单词能否由这个数组中字符连线构成,连线的话只能连上下左右相邻的字母,并且一个字母只能用一次。典型的回溯问题。

虽然问题难度是中等,但是自己却遇到不少坑。一是没太明白回溯和递归的区别和联系,导致在递归处返回,以至于后面的代码压根没执行。二是忘记了回溯进一个分支前要保存当前状态,从这个分支出来后要恢复至原先的状态以便进入下一个分支。就算这样最后代码还是在最后一个比较复杂的测试用例上超时了,即使思路正确。估计是判断过于繁琐了。总之这个题和这个题的hard难度的变种都很有意思。

在贴代码之前先贴上我感觉非常精辟的关于递归和回溯的总结:

回溯和所谓的DFS(深度优先搜索)是一样的。那现在的关键是,怎么实现搜索呢?回溯既然一般使用递归来实现,那个这个递归调用该如何来写呢?我现在的理解就是,进行回溯搜索都会有一系列的步骤,每一步都会进行一些查找。而每一步的情况除了输入会不一样之外,其他的情况都是一致的。这就刚好满足了递归调用的需求。通过把递归结束的条件设置到搜索的最后一步,就可以借用递归的特性来回溯了。因为合法的递归调用总是要回到它的上一层调用的,那么在回溯搜索中,回到上一层调用就是回到了前一个步骤。当在当前步骤找不到一种符合条件情况时,那么后续情况也就不用考虑了,所以就让递归调用返回上一层(也就是回到前一个步骤)找一个以前没有尝试过的情况继续进行。当然有时候为了能够正常的进行继续搜索,需要恢复以前的调用环境。


上面的总结我们只要注意两点就行:1、返回在递归结束后。2、恢复以前的调用环境。


此题实现代码如下(AC版):

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

还有自己的最后一个用例超时版:

public class Test {
	public static void main(String[] args) {

		char[][] board = new char[][] { { 'a', 'b', 'c', 'e' },
				{ 's', 'f', 'e', 's' }, { 'a', 'd', 'e', 'e' } };

	    //char[][] board = new char[][] { { 'a', 'b' } };
		String s = "abceseedasf";

		System.out.println(exist(board, s));
	}

	public static boolean exist(char[][] board, String word) {
		char[] words = word.toCharArray();
		int[] flag = new int[board.length * board[0].length];
		char[] letter = new char[board.length * board[0].length];

		for (int i = 0; i < board.length; i++) {
			for (int j = 0; j < board[0].length; j++) {
				letter[j + i * board[0].length] = board[i][j];
			}
		}

		boolean flags = false;

		for (int i = 0; i < letter.length; i++) {
			if (letter[i] == words[0]) {
				for (int k = 0; k < flag.length; k++) {
					flag[k] = 0;
				}
				flag[i] = 1;
				flags = findBackTracking(letter, i, words, flag,
						board[0].length, 1);
				if (flags) {
					return flags;
				}
			}
		}

		return flags;
	}

	//最后一个测试用例超时,思路是正确的
	
	public static boolean findBackTracking(char[] letter, int startIndex,
			char[] words, int[] flag, int boardlength, int index) {

		if (index == words.length) {
			return true;
		}
		int nowIndex = startIndex;
		boolean flag1 = false, flag2 = false, flag3 = false, flag4 = false;		
		if ((nowIndex - 1 >= 0 && nowIndex - 1 < flag.length)
				&& (nowIndex) % boardlength != 0 && flag[nowIndex - 1] == 0) {
			if (letter[nowIndex - 1] == words[index]) {
				flag[nowIndex - 1] = 1;
				flag1 = findBackTracking(letter, nowIndex - 1, words, flag,
						boardlength, index + 1);
				flag[nowIndex - 1] = 0;
			}
		}

		if ((nowIndex + 1 >= 0 && nowIndex + 1 < flag.length)
				&& (nowIndex + 1) % boardlength != 0 && flag[nowIndex + 1] == 0) {
			if (letter[nowIndex + 1] == words[index]) {
				flag[nowIndex + 1] = 1;
				flag2 = findBackTracking(letter, nowIndex + 1, words, flag,
						boardlength, index + 1);
				flag[nowIndex + 1] = 0;
			}
		}

		if ((nowIndex - boardlength >= 0 && nowIndex - boardlength < flag.length)
				&& flag[nowIndex - boardlength] == 0) {
			if (letter[nowIndex - boardlength] == words[index]) {
				flag[nowIndex - boardlength] = 1;
				flag3 = findBackTracking(letter, nowIndex - boardlength, words,
						flag, boardlength, index + 1);
				flag[nowIndex - boardlength] = 0;
			}

		}

		if ((nowIndex + boardlength >= 0 && nowIndex + boardlength < flag.length)
				&& flag[nowIndex + boardlength] == 0) {
			if (letter[nowIndex + boardlength] == words[index]) {
				flag[nowIndex + boardlength] = 1;
				flag4 = findBackTracking(letter, nowIndex + boardlength, words,
						flag, boardlength, index + 1);
				flag[nowIndex + boardlength] = 0;
			}
		}

		return flag1 || flag2 || flag3 || flag4;
	}
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Typora是一款功能强大的Markdown编辑器,可以实现将Markdown文件导出为Word或PDF格式。在Typora中,通过导出功能,你可以选择将文件导出为Word或PDF格式进行分享或打印。首先,你可以根据Typora中的说明,进入GitHub下载PanDoc。安装完毕后,你可以在Typora中选择导出为Word格式的选项。 如果你想将已有的Word文件导入到Typora中进行编辑,你可以使用终端命令导入。首先打开终端,进入到需要导入的Word文件的文件位置,通过pwd命令查看文件路径。然后,使用以下命令进行导入:pandoc -f docx -t markdown --extract-media /Users/codertutu/Documents -o test.md Typora\ Mac版本安装Pandoc导出文件为word格式(window可通用).docx。其中,/Users/codertutu/Documents为Word文件的路径,test.md为你在Typora中自定义的文件名称,最后一个参数为你的Word文件名称。通过tab键可以进行命令的补全。这样,你就可以在Typora中编辑和导出Word格式的文件了。 希望以上信息能解答你对Typora和Word导出的疑问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [如何让Typora做出Word、Pdf的感觉](https://blog.csdn.net/weixin_46338206/article/details/124227142)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Typora Mac版本安装Pandoc导出文件为word格式(windows可通用)](https://blog.csdn.net/qq_43921353/article/details/126960570)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值