或许每一个武大的学生,都会对小米有不一样的情怀吧。
毕竟雷军作为武大杰出校友已经名满天下,创业经历也足够励志传奇,对学校的情怀也是特别吸粉的一点。
今年4月回武大颁发“雷军奖学金”之后,微博那句“愿你走出半生,归来仍是少年”简直戳中无数少女心,想进小米的情愫早已在心底根种。
所以9月18号小米的笔试我也是尤其用心了,晚上六点半早早坐在电脑前等着,也许我与学长的距离通过这俩小时就大幅缩进了呢。
这里跟大家分享其中两个完整的前端编程题:“杨辉三角”和“排排坐吃果果”(哈哈,这是我给取的名,原谅写程序的小女生就这点乐子了,先卖个关子,到下面跟大家解释)。
题一描述:
一个整数三角形,三角形的每一行都比上面一行多出一个数字(第1行有1个数字,第2行有2个数字,以此类推);每个数字,都等于它上方(如果有的话)与左上方两个数字之和,如下图所示:
现在给出一个数,请算出它最开始出现在第几行?
输入:一个正长整形数,保证为长整形的正数。
输出:这个数最开始出现的行数。
拿到题第一感觉很亲切,感谢小学数学老师每天放学后额外留给我的奥数题,谁也没想到会在十几年后再次遇见“杨辉三角”。事后在网上一搜,发现巨多用编程语言打印出来的“杨辉直角”,C、C++、C#、JAVA……看来大家都是如此的富于乐趣啊
回归正题,一开始想拿着数字去反推,这果断是个错误。
还好思路马上刹车转弯,把这个直角三角形写出来打印出来啊,
每打印一行我就判断一次,判断这一行里有没有给的这个数。
window.onload=function(){
function countNum(x){
if(x==1){return 1} //函数输入1直接返回1
var arr=[[1],[1,1]] //定义数组初始值
for(var i=2;i<x+1;i++){ //从第三行开始创建数据
arr[i]=[]
arr[i].push(1) //每一行第一个默认为0
for(var j=1;j<i;j++){ //从每一行第二列开始遍历
arr[i].push(arr[i-1][j-1]+arr[i-1][j])
//每个数字,都等于它上方(如果有的话)与左上方两个数字之和
}
arr[i].push(1) //每一行最后一个也是1
if(arr[i].indexOf(x)>0){ //完成一行遍历后,查看这一行中有没有需要的数
console.log(arr)
return i+1
}
}
}
console.log(countNum(10))
}
题一只要把思路相对了其实不难,上面的解法也相对简单,大家应该都能看明白。关于题二,个人觉得稍微难点,且看下方分解咯!
题二描述:
食堂有一张靠墙的长桌,规定每个人必须隔着吃饭,不允许挨着。现在长桌上已经有了一些各自独处得人,来了一些新人,判断他们能否找到位置?
输入一个字符串table,只含有0和1,1表示有人,0表示没有人
输入一个正整型的数n,表示新来就餐的人数
输出一个布尔值,能够安排所有的人,返回false,否则返回true
例子:输入1001,1
那么显然没有位置给新来的一个人,返回false
情景转移一下,是不是很像幼儿园里小朋友们,排排坐等着老师发果果吃?怕小朋友们起争执,所以小朋友需要间隔来坐。
原谅我看到这道题真的是脑补了一幅好有爱的画面……
这个问题的关键无非也就是,“有人”=1,“没人”=0,1跟1之间必须隔着0。
也许很多人刚看到题目会想着去找间隔,把0变成1,好吧,我也是这样。
但是这样马上就自己也把自己绕晕了。其实我们不一定要去动这个字符串,换个视野,把这道题看成计数的问题是不是SO EASY?
建模对于编程是如此的重要!
建模对于编程是如此的重要!
建模对于编程是如此的重要!
重要的事情说多少遍都不嫌多,算法题尤其要注意建模思路,
找对思路很简单,要是跑偏了就别提多痛苦,
如果此时的你也正在被一轮轮笔试轰炸,我相信你懂!
这道题我的思路是这样的:
1、先把字符串两边的0找出来,是2的倍数则可以坐一个人,比如001,可以坐一个人,0001还是只能坐一个人,00001可以坐两个人,中间的算法和这个类似,但有所不同
2、再取中间1****1这样的字符串,遇到一个0则将其计数,当遇到下一个1终止计数
3、这时有一个规律,个数为1,2不能坐人0,3,4可以坐一个人,5,6可以坐两个人。。。依次类推
function isOk(table,n){
if(n<=0){return true; } //输入人数为0,直接返回true
if(typeof table=='string'||table instanceof String){ //判断是否是字符串
var start=0,end=0,newTable=[],
arr=table.split(''),length=arr.length
num=0;
//start是第一个1的位置,end是最后一个1的位置,newTable是一个新
//数组,用来存放把两边0截掉后形如1***1这样的字符串
//num用来临时存放一组0的个数
for(var i=0;i<length;i++){
if(arr[i]=='1'){//找出字符串里的第一个“1”
start=i //找到一个1即将索引赋值给start
n=n-parseInt(start/2) //由于0的个数,n减掉部分值
break //找到一个1就停止循环
}
}
for(var j=length-1;j>0;j--){
if(arr[j]=='1'){
end=j
n=n-parseInt((length-1-end)/2)
break
}
}
newTable=arr.slice(start,end+1) //截取掉两边的0后的数组
newTable.forEach(function(item){
if(item=='0'){ //对一组0进行计数
num++
}else if(item=='1'){
n=n-parseInt((num-1)/2) //找全一组后,n减掉部分值
num=0 //并重置num,重新计数
}
})
return n<=0?true:false
//在循环外面判断,n是否被减完了,为了降低某些情况下的遍历次数
//也可以在每次n减完后马上判断n是否小于0,是否需要中止整个操
//作,这种在给定的n比较小的时候能大大降低遍历次数
}else{
return true;
}
}
好辣,排排坐现在也做好了!
总归来说呢,小米的校招知识广度还是有的,除了前端专业知识,算法、操作系统、数据结构、智商情商都有涉及,前面被BAT虐了之后,做完小米的题竟然会觉得学长的店还是些许温柔的。
关于上面两道题,欢迎大家有好的思路跟我讨论,其实我都不好意思说这两套解法已经是我经过了几个小时琢磨后的成果了。考试毕竟跟平时的心态会有变化,尤其是我一紧张脑子就不好使,有好的面经笔经还望各位不吝赐教辣,小女子在此谢过!