這是一道大約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 + ")"); } }