这是一道大约15年这个时候我去某B开头的互联网公司面试时的一道基础算法题,其描述是有一只小老鼠,假设其在(x,y)点,它的初始方向为Y轴负半轴,它不能碰到x,y轴,也不能与本身走过的路径重合。而且其所走的全部坐标点必须<=(x,y),求它走过的路径和最终停在哪一个点。java
当时我并无在限定时间解出这道题,现在在作BFS迷宫算法题时忽然看到了二者存在某种一致性(固然本题更简单,并不须要用到BFS),勾起了陈年旧事,便一解以了。面试
其实本题最重要的思路有三点算法
1. 利用二维数组解坐标问题数组
这里须要注意的是,二维数组的行其实在数学通常坐标系中是Y轴,其列是X轴。然而直观上又会有行是X轴列是Y轴的印象。从前我常常边作边在内心置换,一会就把本身搞混乱了。其实坐标系只是相对的(相同的坐标值能够根据本身的偏好作出不一样的坐标系,而其结果实际上是相同的),即你能够直观地把行当作x,列当作y,只要你在做图的时候也按照这个概念,将x轴作成y,y轴作成x就能够了,须要注意的是,为了更加直观,能够取第四象限为做图起始。oop
2. 本题存在一个退出条件,即上下左右四个点都已是visited,这样便须要在定义数组的时候多定义一行一列。其实用二维数组解坐标问题,自己就须要多定义一行一列(若是坐标点是(3,5),那么x有0,1,2,3四个数,须要四行存放),而本题中须要更多地定义一列(即若是坐标点是(3,5),数组应该是(3+2,5+2),不然在判断边界点时判断语句会由于数组溢出而报错。在初始化时须要将边界所有置为已经访问过的点(这些点原本就是不能触碰的)blog
3. 命名要有明确的含义,要直观,而不要绕弯。好比定义boolean visited[][]数组存放各个点的访问状况,若是已经访问了该节点,则置为true,若是还未访问,就是初始值false。虽然否认之否认是确定,但若是命名为unvisited,再把结果倒置,实在是麻烦了本身也麻烦了程序。(T_T这就是我最初的作法,本身把本身搞凌乱了)数学
以上就是我作这道题的时的感悟了it
public class loop { public static int N = 5, M = 7; public static void main(String args[]) { int x = 3, y = 5; boolean visited[][] = new boolean[5][7]; for (int i = 0; i < 7; i++) { visited[0][i] = true; visited[4][i] = true; } for (int i = 0; i < 5; i++) { visited[i][0] = true; visited[i][6] = true; } int dir[][] = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } }; System.out.println("Visit:(" + x + ", " + y + ")"); visited[x][y] = true; while (x >= 1 && x <= N && y >= 1 && y <= M && (!visited[x + dir[0][0]][y + dir[0][1]] || !visited[x + dir[1][0]][y + dir[1][1]] || !visited[x + dir[2][0]][y + dir[2][1]] || !visited[x + dir[3][0]][y + dir[3][1]])) { for (int i = 0; i < 4; i++) { while (x >= 0 && x <= M && y >= 0 && y <= N && !visited[x + dir[i][0]][y + dir[i][1]]) { x = x + dir[i][0]; y = y + dir[i][1]; visited[x][y] = true; System.out.println(dir[i][0] + "," + dir[i][1]); System.out.println(visited[x][y]); System.out.println("Current Location:(" + x + ", " + y + ")"); } } } System.out.println("The final point is:(" + x + ", " + y + ")"); } }