好久没有写博客,主要是最近欠了太多文档,一直在写文档,写到崩溃。。。
前些天,在网站上看到一个面试题,我看了下,是一道基础的模拟题,正可以用来缓解我被文档摧残的乏累
上面试题:
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);
代码上说明不是很多,哪里有问题,可以评论告诉我 ^ ^