* 面试题12:矩阵中的路径
* 题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。
* 路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一个。
* 如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。
* 例如:3*4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用下划线标出)
* 但矩阵中不包含字符串“abfd”的路径,
* 因为字符串的第一个字符b占据了矩阵的第一行第二个各自以后,路径就不能再次进入这个格子。
*
* 思路:设置一个标记位,标记进入过的元素。
* 循环遍历二维数组,首先找到起点(第一个元素的值),标记位true
* 然后再对此元素的上下左右四个位置进行递归查找,若是这四个都没有,则还原到原来的位置,返回false
* 若是有一个则进行分支检查judge(),继续上一步的操作(上下左右),直到找到true或者找不到false
* 结束条件:或长度不符,或直到将数组所有元素都走完
package Test;
import java.util.Scanner;
public class No12hasPath {
/*
* 面试题12:矩阵中的路径
* 题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。
* 路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一个。
* 如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。
* 例如:3*4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用下划线标出)
* 但矩阵中不包含字符串“abfd”的路径,
* 因为字符串的第一个字符b占据了矩阵的第一行第二个各自以后,路径就不能再次进入这个格子。
*
* 思路:设置一个标记位,标记进入过的元素。
* 循环遍历二维数组,首先找到起点(第一个元素的值),标记位true
* 然后再对此元素的上下左右四个位置进行递归查找,若是这四个都没有,则还原到原来的位置,返回false
* 若是有一个则进行分支检查judge(),继续上一步的操作(上下左右),直到找到true或者找不到false
* 结束条件:或长度不符,或直到将数组所有元素都走完
* */
public static void main(String[] args) {
// TODO Auto-generated method stub
No12hasPath path = new No12hasPath();
Scanner in = new Scanner(System.in);
System.out.println("输入一个字符串序列(3行4列的矩阵):");
String str = in.nextLine();
char[] matrix = str.toCharArray();
int rows = 3;
int cols = 4;
//要查找的字符串
String s = in.nextLine();
//判断s这个字符串是否在matrix中 ,在则返回true,否则false
boolean flag = path.hasPath(matrix,rows,cols,s.toCharArray());
if(flag == true) {
System.out.println("字符串"+s+"在str数组中。");
}
else {
System.out.println("字符串"+s+"不在str数组中。");
}
}
private boolean hasPath(char[] matrix, int rows, int cols, char[] s) {
// TODO Auto-generated method stub
//标志位flag 初始化为false----标识二维数组中每一个格子是否已经进入过了
boolean[] flag = new boolean[matrix.length];
for(int i=0;i<rows;i++) {
for(int j=0;j<cols;j++) {
//循环遍历二维数组,首先找到起点等于s(第一个元素)的值,再递归判断四周是否有符合条件的
//若没有,则进行j++,直到一行结束
//再进行下一行的查询i++
//直到走完整个数组,或者找到了这一字符串
if(judge(matrix,i,j,rows,cols,flag,s,0)) {
//首先查找第一个字符X 是否在matrix的二维数组中
//并再找到第一个元素后,对周围的元素进行遍历,查看是否有和要查找的字符串一致的
return true;
}
}
}
return false;
}
//judge(初始矩阵matrix,索引行坐标i,索引纵坐标j,矩阵行数,矩阵列数,带判断的字符串,字符串索引初始为0即先判断字符串的第一位)
//首先判断是否有第一个字符,再判断是否有这个字符串(也是一个一个字符进行判断)
private boolean judge(char[] matrix, int i, int j, int rows, int cols, boolean[] flag, char[] s, int k) {
// TODO Auto-generated method stub
//先根据i和j二维数组的行列值,计算匹配的第一个元素转为一维数组的位置
int index = i*cols+j;
//若i<0,j<0,i>rows,j>cols,matrix[index]!=s[k],flag[index]标志位为true表示进入过这个格子,则都返回false
if(i<0||j<0||i>=rows||j>=cols||matrix[index]!=s[k]||flag[index]==true) {
return false;
}
//若k等于s.length-1表示k已经到达s的末尾,说明之前的都已经匹配成功,直接返回true即可
if(k==s.length-1) {
return true;
}
//将这个定位的格子,标记为true
flag[index] = true;
//对数组进行回溯,递归寻找,每次找到了就将k+1,若找不到,则还原
if(judge(matrix,i-1,j,rows,cols,flag, s,k+1)||
judge(matrix,i,j-1,rows,cols,flag,s,k+1)||
judge(matrix,i+1,j,rows,cols,flag,s,k+1)||
judge(matrix,i,j+1,rows,cols,flag,s,k+1)) {
return true;
}
//若是没有一条路是通的,则还原,尝试其他路经
flag[index] = false;
return false;
}
}
* 面试题13:机器人的运动范围
* 题目:地上有一个m行n列的方格。一个机器人从坐标(0,0)的格子开始移动,
* 它每次可以向上、下、左、右移动一格,但不能进入行坐标和列坐标的数位之和大于k的格子
* 例如:当k为18时,机器人能够进入方格为(35,37),因为3+5+3+7=18.
* 但它不能进(35,38),因为3+5+3+8=19.
* 请问该机器人能够到达多少个格子
*
*
*
*思路:用一个flag标志位标记是否已经进入过该格子
* 声明一个全局变量可以统计能进的坐标的数量
* 然后从(0,0)开始计算,先标记这个格子,在进行查看周围的格子
* 并计算是否位数和大于k,若大于则可能进入,否则可以进入
* 对此位置的上下左右递归进行查询,直到所有的统计完
package Test;
import java.util.Scanner;
public class No13movingCount {
/*
* 面试题13:机器人的运动范围
* 题目:地上有一个m行n列的方格。一个机器人从坐标(0,0)的格子开始移动,
* 它每次可以向上、下、左、右移动一格,但不能进入行坐标和列坐标的数位之和大于k的格子
* 例如:当k为18时,机器人能够进入方格为(35,37),因为3+5+3+7=18.
* 但它不能进(35,38),因为3+5+3+8=19.
* 请问该机器人能够到达多少个格子
*
*
*
*思路:用一个flag标志位标记是否已经进入过该格子
* 声明一个全局变量可以统计能进的坐标的数量
* 然后从(0,0)开始计算,先标记这个格子,在进行查看周围的格子
* 并计算是否位数和大于k,若大于则可能进入,否则可以进入
* 对此位置的上下左右递归进行查询,直到所有的统计完
* */
static int counter = 0;
public static void main(String[] args) {
// TODO Auto-generated method stub
No13movingCount count = new No13movingCount();
Scanner in = new Scanner(System.in);
//k值--行坐标和列坐标的数位之和不能够大于k值
System.out.println("输入行坐标和列坐标的位数之和不能超过的k值大小:");
int k = in.nextInt();
//rows行cols列的方格
System.out.println("依次输入行、列的大小:");
int rows = in.nextInt();
int cols = in.nextInt();
count.movingCount(rows,cols,k);
System.out.println("机器人在"+rows+"行"+cols+"列的方格中能够到达"+counter+"个格子");
}
//计算机器人能够到达多少个格子
private void movingCount(int rows, int cols, int k) {
// TODO Auto-generated method stub
if(k<=0) {
return ;
}
//标志位flag,记录是否进入过该格子 1表示进入过,0表示还未进入过
int[] flag = new int[rows*cols];
moving(rows,cols,0,0,k,flag);
}
private void moving(int rows, int cols, int i, int j, int k,int[] flag) {
// TODO Auto-generated method stub
//计算出该字符在一维数组中的位置index
int index = i*cols+j;
if(i<0||j<0||i>=rows||j>=cols||flag[index]==1) {
return ;
}
//计算行坐标和列坐标的位数之和
int sumOfi = sumOfNumber(i);
int sumOfj = sumOfNumber(j);
//标记index位置的flag,表示进入过该位置了
flag[index] = 1;
if(sumOfi+sumOfj <= k) {
counter++;
}
else {
return ;
}
//对该位置的上下左右进行判断
moving(rows,cols,i-1,j,k,flag);
moving(rows,cols,i,j-1,k,flag);
moving(rows,cols,i+1,j,k,flag);
moving(rows,cols,i,j+1,k,flag);
}
//计算位数之和
private int sumOfNumber(int i) {
// TODO Auto-generated method stub
return (i%10)+(i/10);
}
}