HI啊,又到了一个礼拜一次的烧脑时间,其实这一次我真的很怕生不出来,所以我礼拜一就开始準备了,哈哈哈,今天的题目其实上礼拜就要Po了,可是那时候真的在电脑前面鬼打墙很久,就直接换到Hard难度的SQL题目了,所以这篇算是来还债的XD,感谢大家持续支持这个系列
这一次的题目有些人应该会很熟悉,其实就题目名称来说也算满常听到的,只是小的我第一次碰到,所以实作时苦恼很久,那还是一样废话不多说,直接来吧!
题目名称:Spiral Matrix
难易度:中
题目内容:传入一个二维阵列,依序由上、右、下、左,从外面往里面用螺旋的方式取值,回传该阵列中的所有元素。
例如:
1.传入以下阵列:
[
[1,2,3],
[4,5,6],
[7,8,9]
]
会回传阵列:[1,2,3,6,9,8,7,4,5]
2.传入以下阵列:
[
[1, 2, 3 ],
[4, 5, 6 ],
[7, 8, 9 ],
[10,11,12]
]
会回传阵列:[1,2,3,6,9,12,11,10,7,4,5,8]
好的,那以下是我苦思后的解法:
var spiralOrder = function(matrix) { //如果传进来是空阵列就回传空阵列 if(matrix.length === 0){ return []; } //用来装解答 let ans = []; //阵列中所有的数字有几个 let indexCount = matrix.length * matrix[0].length; //用来记录目前的流程(0:上,1:右,2:下,3:左) let seq = 0; //指定回传的位置值 //第一维度是x,第二维度是y(等等进入迴圈后y会先+1所以初始值为-1) let x = 0; let y = -1; //跑迴圈(如果解答阵列中的长度小于matrix的所有元素就继续跑,因为ans最后的阵列长度一定会和matrix一样) while(ans.length < indexCount){ //指定位置 changeIndex(1); //宣告一个变数用来放目前要抓的值 let nowValue; //取值用try迴圈包起来 try{ //用目前指定的位置把值从阵列取出来 nowValue = matrix[x][y]; } catch(err){ //如果超出该阵列範围就回传undefined nowValue = undefined; }; //如果回传的值不在ans里面又不是undefined就把他放进ans中 if(ans.indexOf(nowValue) ===- 1 && nowValue !== undefined){ ans.push(nowValue); } else{ /*这里是因为如果取出来undefuned或是重複的值, 要先把这一次迴圈加的位置减回来, 等于回复进入这一次迴圈前的状态。*/ changeIndex(-1); //这里用来变动流程,依序由上:0,右:1,下:2,左:3去取值 if(seq === 3){ seq = 0; } else{ seq+=1; } }; }; //用来变动位置,index传入变动值 function changeIndex (index){ //确认目前流程,依照流程来做变动(如果传进-1就是回复之前的状态) switch(seq){ case 0:{ //如果是0(上),就是往右一格,所以y+1 y+=index; break; }; case 1:{ //如果是1(右),就是往下一格,所以x+1 x+=index; break; }; case 2:{ //如果是2(下),就是往左一格,所以y-1 y-=index; break; }; case 3:{ //如果是3(左),就是往上一格,所以x-1 x-=index; break; }; }; }; //最后回传装完所有值的阵列 return ans; };
接着我分享一下这一次的成绩,执行时间大概是56ms,然后赢过了77.16%的解答,其实一开始我送答案的时候才7%,一个吓到吃手手,立马修了第二版本出来XD,另外之前SQL之所以没有贴上执行成绩是因为送答案的人太少了,才让那个系统没办法产生图表,所以这一次分享一下!
还有我在讨论区看到一个赢过95%答案的神之解答,完全用函式解决一堆逻辑上的问题,看完后真觉得自己对JS的熟练度还真的低到爆炸XD,那来看一下大神解法:
原解答网址
var spiralOrder = function (matrix) { "use strict"; //宣告一个新阵列 var res = []; //一个function来判断阵列内是否还有值,如果有就回传false,没有就true var isEmpty = function isEmpty() { return matrix.length === 0 || matrix[0].length === 0; }; //如果他还不是空的就继续跑迴圈 while (!isEmpty()) { //抓出matrix的第一个阵列位置,并把他放进res中(处理上面的部分) res = res.concat(matrix.shift()); //确认目标阵列是否为空,如果是空的就跳出 if (isEmpty()) break; //去跑迴圈,经过目前的所有位置 for (var i = 0; i < matrix.length; i++) { //把每个位置的最后一个值抓出来放进res中(处理右边的部分) res.push(matrix[i].pop()); } //确认目标阵列是否为空,如果是空的就跳出 if (isEmpty()) break; //把最后一个位置抓出来,反转后放进res中(处理下面的部份) res = res.concat(matrix.pop().reverse()); //确认目标阵列是否为空,如果是空的就跳出 if (isEmpty()) break; //去跑迴圈,经过目前的所有位置 for (var _i = matrix.length - 1; _i >= 0; _i--) { //把每个位置的第一个值抓出来放进res中(处理左边的部分) res.push(matrix[_i].shift()); } } //重複以上流程,直到目标阵列被处理到空了为止。 return res;};
上面的程式码可能会和原文解答有点不同,因为我把它从ES6转到ES5的语法,也照惯例的加了一堆注解,不然我真的还不太熟ES6
那以上是这礼拜的分享,虽然总算回到熟悉的JavaScript但也同时觉得世界还很大,有更多要学习的地方,算是一个收穫满满的一个礼拜XD。那一样欢迎各位大大一起来讨论各自的解法,如果以上文章中有不小心手误、或是有问题的地方还请大家告诉我,我会立即改进!这一週依然感谢大家!没有你们我一定坚持不到现在!