【算法】回溯法四步走 (15)

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。

[["a","b","c","e"],
["s","f","c","s"],
["a","d","e","e"]]

但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。

示例 1:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED" 输出:true

示例 2:

输入:board = [["a","b"],["c","d"]], word = "abcd" 输出:false 答案(flag)

我们使用flag代表已找到,剪枝;并且使用used数组指明访问过的元素。

class Solution { public char[][] board; public String word; public char[] chars; public boolean[][] used; public boolean flag; // 找到了,就不用递归了 public boolean exist(char[][] board, String word) { this.board = board; this.word = word; this.chars = word.toCharArray(); used = new boolean[board.length][board[0].length]; for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { dfs(0, i, j); } } return flag; } // 走迷宫,递归回溯法 // 状态:当前位置x、y,当前字符在字符串中的索引index public void dfs(int index, int x, int y) { if (index > word.length() - 1) { this.flag = true; return; } if (x < 0 || x > board.length - 1 || y < 0 || y > board[0].length - 1 || used[x][y] || flag || board[x][y] != chars[index] ) { return; } used[x][y] = true; index++; // 开始右下左上 dfs(index, x, y + 1); // 右 dfs(index, x + 1, y); // 下 dfs(index, x, y - 1); // 左 dfs(index, x - 1, y); // 上 used[x][y] = false; } } 答案(返回true) // 之前的算法(不是上面的,上面我加了flag进行优化),我与别人的差距在于,别人找到了就直接跳出递归了,而我还要一直找下去,直到遍历完 // 现在是第二种优化方案! class Solution { public char[][] board; public String word; public char[] chars; public boolean[][] used; public boolean exist(char[][] board, String word) { this.board = board; this.word = word; this.chars = word.toCharArray(); used = 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(0, i, j)) { return true; } } } return false; } // 走迷宫,递归回溯法 // 状态:当前位置x、y,当前字符在字符串中的索引index public boolean dfs(int index, int x, int y) { if (index > word.length() - 1) { return true; } if (x < 0 || x > board.length - 1 || y < 0 || y > board[0].length - 1 || used[x][y] || board[x][y] != chars[index] ) { return false; } used[x][y] = true; index++; // 开始右下左上 boolean res = dfs(index, x, y + 1) || dfs(index, x + 1, y) || dfs(index, x, y - 1) || dfs(index, x - 1, y); used[x][y] = false; return res; } } 使用\'\0\'代表已访问

我们使用返回值true代表已找到,剪枝;并且使用\'\0\'指明访问过的元素。

class Solution { public boolean exist(char[][] board, String word) { char[] words = word.toCharArray(); for(int i = 0; i < board.length; i++) { for(int j = 0; j < board[0].length; j++) { if(dfs(board, words, i, j, 0)) return true; } } return false; } boolean dfs(char[][] board, char[] word, int i, int j, int k) { if(i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != word[k]) return false; if(k == word.length - 1) return true; board[i][j] = \'\0\'; boolean res = dfs(board, word, i + 1, j, k + 1) || dfs(board, word, i - 1, j, k + 1) || dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i , j - 1, k + 1); board[i][j] = word[k]; return res; } } 46. 全排列

给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]
输出:

[ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 我的答案

这个答案应该是一般人的第一个思路。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwwszw.html