面試題:風車數字數組

好久沒有寫博客,主要是最近欠了太多文檔,一直在寫文檔,寫到崩潰。。。
前些天,在網站上看到一個面試題,我看了下,是一道基礎的模擬題,正可以用來緩解我被文檔摧殘的乏累

上面試題:

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

代碼上說明不是很多,哪裏有問題,可以評論告訴我 ^ ^

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