2021.02.07 矩阵中的路径
今日题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。
[[“a”,”b”,”c”,”e”],
[“s”,”f”,”c”,”s”],
[“a”,”d”,”e”,”e”]]
但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。

提示:
- 1 <= board.length <= 200
1 <= board[i].length <= 200
思路:
本质上就是深度有限搜索。设置两个全局变量word(String)、tag(boolean[][] 记录是否已经访问过),然后遍历二维矩阵中的每个元素,以目前元素为起点,查看是否存在路径,若是存在则直接返回true,遍历结束后若是不存在则直接返回false。
- 算法过程:
hasPath(row, col, length, board):用于判断是否含有路径,row、col表示要比较字符所处的行、列,length表示要比较字符在字符串中的索引值。
若length == word.length(),表示已比对完毕,存在路径。
否则在row、col的值合法、board[row][col] == word.charAt(length)、board[row][col]未被访问的情况下,length+1,继续判断该位置的上下左右四个方向是否存在剩下的路径,用has记录判断结果,若不存在剩下的路径,则回退,最后返回has。
大佬改进版本则直接省去了tag标记数组。
自己的菜鸡代码: ```java class Solution { private boolean[][] tag; private String word; public boolean exist(char[][] board, String word) {
if(board.length == 0 || word.length() == 0) return false;//自动初始化为falsethis.tag = new boolean[board.length][board[0].length];this.word = word;for(int i = 0; i < board.length; i++){for(int j = 0; j < board[0].length; j++){if(hasPath(i, j, 0, board)){return true;}}}return false;
}
boolean hasPath(int row, int col, int length, char[][] board){
// 判断是否存在路径if(length == word.length()) return true;boolean has = false;if(row >= 0 && row < board.length && col >= 0 && col < board[0].length && word.charAt(length) == board[row][col]&& !tag[row][col]){++length;tag[row][col] = true;has = hasPath(row, col-1, length, board) || hasPath(row, col+1, length, board)|| hasPath(row-1, col, length, board) || hasPath(row+1, col, length, board);if(!has){// 回退--length;tag[row][col] = false;}}return has;
} }
// 大佬改进版本的
- 运行结果:<a name="clwS3"></a>### 2021.02.07 机器人的运动范围今日题目:地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?<br /><br />提示:- 1 <= n,m <= 100- 0 <= k <= 20- 思路:这题也是用深度优先搜索的方法。算法过程:- countPath(int row, int col) :用于递归计算路径长度检查row、col值是否符合要求,若是不符合则返回0;否则返回 1+ 上下左右的可达路径长度。- check(int row, int col):用于检查row、col的值是否符合要求。用value来记录每次的数位之和。<br />不符合的情况:row < 0 || row >= rows || col < 0 || col >= cols、value > k。返回false。<br />符合的话则返回true。- 自己的菜鸡代码:```javaclass Solution {private boolean[][] tag;private int k;private int rows;private int cols;public int movingCount(int m, int n, int k) {this.tag = new boolean[m][n];this.k = k;this.rows = m;this.cols = n;return countPath(0, 0);}int countPath(int row, int col){// 用于计算路径长度int count = 0;if(check(row,col)){tag[row][col] = true;count = 1 + countPath(row, col+1) + countPath(row, col-1) + countPath(row+1, col) + countPath(row-1, col);}return count;}boolean check(int row, int col){if(row < 0 || row >= rows || col < 0 || col >= cols) return false;int value = row / 10 + row % 10 + col / 10 + col % 10;if(value <= k && !tag[row][col]) return true;return false;}}
- 运行结果:

2021.01.22 二叉树中和为某一值的路径(思路还没写)
今日题目:输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。

提示:节点总数 <= 10000
- 思路:这题也好烦555。
自己的菜鸡代码:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/class Solution {private LinkedList<List<Integer>> lists = new LinkedList<>();private LinkedList<Integer> list = new LinkedList<>();public List<List<Integer>> pathSum(TreeNode root, int sum) {// 本质上是先序遍历dfs(root, sum);return lists;}void dfs(TreeNode root, int sum){// 怎么回溯if(root == null) return;list.add(root.val);sum -= root.val;if(root.left == null && root.right == null && sum == 0){lists.add(new LinkedList<>(list));}dfs(root.left, sum);dfs(root.right, sum);list.removeLast();}}
运行结果:



2021.02.18 字符串的排列
今日题目:输入一个字符串,打印出该字符串中字符的所有排列。你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
限制:1 <= s 的长度 <= 8
- 思路:(回溯法)分为两步,第一步是将字符串的第一个字符与后边的字符逐个交换;第二步是固定第一个字符,将后边的部分作为一个字符串整体继续进行相同的操作,很明显就是递归。第三步就是将现第一个字符与原第一个字符交换,即恢复到原来(回溯)。
需要注意的地方:
因为字符串中可能会出现的字符,所以要进行去重操作,设立一个HashSet用于该字符串中已经当过第一个字符的字符,当在每一层的字符串第一个结点与后边相交换时,检查HashSet中是否已经包含后边待交换的字符,若已包含,则直接跳过。
自己的菜鸡代码:
class Solution {private List<String> res = new ArrayList<>();;private char[] s;public String[] permutation(String s) {this.s = s.toCharArray();dfs(0);return res.toArray(new String[res.size()]);}void dfs(int cur){if(cur == s.length - 1){res.add(String.valueOf(s));}else{HashSet<Character> set = new HashSet<>();for(int i = cur; i < s.length; i++){if(set.contains(s[i])) continue;set.add(s[i]);char temp = s[cur];s[cur] = s[i];s[i] = temp;dfs(cur + 1);// 再交换回来temp = s[cur];s[cur] = s[i];s[i] = temp;}}}}
运行结果:

