面试题:风车数字数组

好久没有写博客,主要是最近欠了太多文档,一直在写文档,写到崩溃。。。
前些天,在网站上看到一个面试题,我看了下,是一道基础的模拟题,正可以用来缓解我被文档摧残的乏累

上面试题:

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);

代码上说明不是很多,哪里有问题,可以评论告诉我 ^ ^

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章