剑指Offer面试题(第九天)面试题12、13

 * 面试题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);
	}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值