好久沒有寫博客,主要是最近欠了太多文檔,一直在寫文檔,寫到崩潰。。。
前些天,在網站上看到一個面試題,我看了下,是一道基礎的模擬題,正可以用來緩解我被文檔摧殘的乏累
上面試題:
foo(1) = [[1]];
foo(2) = [ [1, 2]
[4, 3] ];
foo(3) = [ [7, 8, 9]
[6, 1, 2]
[5, 4, 3] ];
foo(4) = [ [7, 8, 9, 10]
[6, 1, 2, 11]
[5, 4, 3, 12]
[16, 15, 14, 13] ];
依此類推。。。
foo(n)
題目解析:要生成一個二維數組,數組內填寫的是從一開始的數字,一個一個推導發現,如圖
emmmm,與其說是題目上描述的風車,不如說回型更爲貼切。數字的邏輯爲 foo(n) 數組內的數值爲1 - n^2。
再進一步觀察,因爲要走回型路線,所以起點 1 應該都是在中心位置,那麼再次思考,如果數組沒有正中心位置(例如 foo(4) ),那麼起點應該在偏向哪邊的點。關於這一點,我是通過行走方向推斷的,數組從起點行走的方向都是:右 -> 下 -> 左 -> 上 。所以起點應該是在正中心或是正中偏左上的位置。
中心點和數組大小已經定下來,先做數組的初始化,代碼如下:
// 入口
function foo(num) {
let arr = draw(num);
console.log(arr);
}
function draw(num) {
let arr = init(num);
let center = {
x: Math.floor((num - 1) / 2),
y: Math.floor((num - 1) / 2)
}
arr[center.x][center.y] = 1;
return arr;
}
function init(num) {
let arr = new Array();
for (let i = 0; i < num; i++) {
arr[i] = new Array();
for (let j = 0; j < num; j++) {
arr[i][j] = 0;
}
}
return arr;
}
foo(4);
此時輸出的結果爲:
好了,我們起點都設好了,那麼就要開始走了,走的方向我們之前也有提及,爲:右 -> 下 -> 左 -> 上 。那麼現在的問題是,我們應該每個方向走幾步呢?如果一直糾結在走幾步,我們就會需要大量的時間去一個一個推導,找尋規律。那麼,我們換一個方向思考,從起點開始,我們每個方向只走一步,右走一步,往下走一步,往左走一步,現在該往上走一步了,但是,走的時候發現上面那一格已經走過了(因爲數值不爲0了),所以,我們不能換方向,那麼再按原來的方向向左走一步,接下來該向上走了,發現可以走了,那麼下一步我們就要向上走。。。。以此類推
結論:這個模擬題的走路方式就是按着右 -> 下 -> 左 -> 上,4個方向循環依此走,發現下一個方向的格子已經走過了,那麼就按照現在的方向繼續走,走一個,看一下下一個方向是否可以走了,如果可以走了,就按下一個方向繼續走,按此邏輯,直到結束。
結束標誌:我們從1開始走,走一步 +1 ,並更新該位置的數值,直到數值爲 n^2 ,則爲結束。
完整代碼如下:
let arr = new Array(); // 我們將數組全局化,以便後面的遞歸
let drawNum = 1; // 計數器
let dir = [[0, 1], [1, 0], [0, -1], [-1, 0]]; // 右 下 左 上,四個方向對數組(x, y) 的操作
function foo(num) {
draw(num);
console.log(arr);
}
function draw(num) {
init(num);
let center = {
x: Math.floor((num - 1) / 2),
y: Math.floor((num - 1) / 2)
}
arr[center.x][center.y] = drawNum;
startWalk(center, -1, num);
return arr;
}
function init(num) {
for (let i = 0; i < num; i++) {
arr[i] = new Array();
for (let j = 0; j < num; j++) {
arr[i][j] = 0;
}
}
}
function startWalk(start, index, num) {
if (drawNum == num*num) {
return ;
}
let nextIndex = (index + 1) % 4;
let point = {
x: start.x + dir[nextIndex][0],
y: start.y + dir[nextIndex][1]
}
if (arr[point.x][point.y] != 0) {
point.x = start.x + dir[index][0];
point.y = start.y + dir[index][1];
} else {
index = nextIndex;
}
arr[point.x][point.y] = ++drawNum;
startWalk(point, index, num);
}
foo(4);
代碼上說明不是很多,哪裏有問題,可以評論告訴我 ^ ^