12.
题目:
剑指 Offer 12. 矩阵中的路径https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof/
想法:从某点开始"走",上下左右都可以,但也有很多不可以,如
1.边界不可以
2.走过的不可以
3.和字符串不匹配的不可以
带着这种想法写了三层循环,但发现不好判断走过的,也不好记录何时走下一个(因为设定的上下左右都试试,但可能上就可以了,下左右没走),后改成递归写法,递归掌握不熟练!
代码:
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++){
//遍历起始点(题目中没有说一定从0,0开始搜索)
if(findPath(board,words,i,j,0))
//若找到则返回true,否则查找下一个开头
return true;
}
}
return false;
}
boolean findPath(char[][] board,char[] words,int i,int j,int c){
if(i<0||j<0||i==board.length||j==board[0].length)
//抵达边界返回false
return false;
if(board[i][j]!=words[c])
//当前值与字符串中不同
return false;
//即:如能走到下面的代码,则说明当前board[i][j]==words[c]
if(c==words.length-1)
//最后一个c也匹配,即全部能够匹配
return true;
//访问过设为空,用于下次检查不重复访问
board[i][j]='\0';
//访问周围四个 上下左右 只要有一个能走通就行 所以是或
boolean res=findPath(board,words,i-1,j,c+1)||
findPath(board,words,i+1,j,c+1)||
findPath(board,words,i,j-1,c+1)||
findPath(board,words,i,j+1,c+1);
//还需重置board[i][j],因为要从不同出发点多次搜索路径
board[i][j]=words[c];
return res;
}
}
结果:
13.
题目:
剑指 Offer 13. 机器人的运动范围https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/
想法:感觉磁体和上题很相似,只是入参没有了数组,但想着还是需要记录某点是否访问过,则建立的flag二维数组,用递归作答(有返回值和无返回值两种).
不可走的情况:(可走时cnt++)
1.边界不可以
2.访问过不可以
3.不满足k的条件不可以
代码:
//递归有返回值 flag是boolean
class Solution {
public int movingCount(int m, int n, int k) {
boolean[][] flag=new boolean[m][n];
return findPath(flag,0,0,k);
}
private int findPath(boolean[][] flag,int i,int j,int k){
if(i<0||j<0||i==flag.length||j==flag[0].length)
//抵达边界返回false
return 0;
if(i%10+i/10+j%10+j/10>k)
//当前值与字符串中不同
return 0;
if(flag[i][j])
//已访问过 不要重复访问
return 0;
//该点设为已访问
flag[i][j]=true;
//访问周围四个 上下左右 只要有一个能走通就行 所以是或
return 1+findPath(flag,i+1,j,k)
+findPath(flag,i,j+1,k);
// 每次遍历时上和左已遍历故只遍历右和下即可
// +findPath(flag,i-1,j,k)
// +findPath(flag,i,j-1,k)
}
}
//递归无返回值 flag是int
class Solution {
int cnt=0;
public int movingCount(int m, int n, int k) {
int[][] flag=new int[m][n];
findPath(flag,0,0,k);
return cnt;
}
void findPath(int[][] flag,int i,int j,int k){
if(i<0||j<0||i==flag.length||j==flag[0].length)
//抵达边界返回false
return;
if(i/10+i%10+j/10+j%10>k)
//当前值与字符串中不同
return;
if(flag[i][j]==0)
cnt++;
else
return;
flag[i][j]=1;
//访问周围四个 上下左右 只要有一个能走通就行 所以是或
findPath(flag,i+1,j,k);
findPath(flag,i,j+1,k);
}
}
又学到了:给定一个数字n,计算该数的数位和的函数
private int bitSum(int n) {
int sum = 0;
while(n > 0) {
sum += n % 10;
n /= 10;
}
return sum;
}
结果:
遍历上下左右:
只遍历右下: