《程序员模拟器》生涯普通1~18关攻略
修改于昨天 00:5819 浏览攻略
这份攻略整理的是一些过关思路,不是唯一解,更不是标准答案。很多关卡我自己也卡过,后来翻论坛、看别人分享才慢慢摸清楚。本人非专业人士,如果有写错的地方,欢迎大家指出!游戏有自己的规则,哪怕你写过 JavaScript,也得重新适应——比如游戏键盘里打不出冒号、分号和问号等,常见的 for 循环、对象字面量还有简洁的判断也就用不上。如果你是第一次接触普通难度,建议先自己试试。这部分的题目开始有点意思了——暴力能过,但动动脑子能找到更巧的办法,实在卡住再来看攻略也不迟。
另外,普通难度依然有输入格式的小陷阱,比如套了两层的数组,代码里我都标出来了。
最后还是那句话:解法没有高下之分,能跑通就是好代码,享受琢磨的过程就好。PS如果想单独复制某一关的代码,建议用手机浏览器打开此攻略,而不是客户端


生涯模式攻略导航:


1. 质数
判断一个数是否为质数,只需检查它是否存在小于或等于其平方根的因数。平方根可以用1/2次幂表示,也可以手敲Math.sqrt(变量a)
变量a=输入
变量b=变量a**(1/2)
变量c=2
while ( 变量c<变量b ){
if ( 变量a%变量c==0 ){
return false
}
变量c+=1
}
return true
2. 上楼梯
经典的三阶斐波那契,f(n) = f(n-1) + f(n-2) + f(n-3)。这里不断追加n到数组里
变量a=输入
变量b=[1,1,2]
变量c=3
while ( 变量c<=变量a ){
变量d=变量b[变量c-1]+变量b[变量c-2]
+变量b[变量c-3]
变量b.push( 变量d )
变量c+=1
}
return 变量b[变量a]
3. 最大公约数
从较小的数开始往下找,用Math.min取输入两个数中较小的数
解法一(暴力枚举)
变量a=输入[0]
变量b=输入[1]
变量c=Math.min(变量a,变量b)
while ( 变量c>1 ){
if (变量a%变量c==0
&& 变量b%变量c==0){
return 变量c
}
变量c-=1
}
return 变量c
解法二(辗转相除法,经典,优雅)
变量a=输入[0]
变量b=输入[1]
while ( 变量b!=0 ){
变量c=变量a%变量b
变量a=变量b
变量b=变量c
}
return 变量a
4. 最小公倍数
枚举倍数:用其中一个数的倍数去试,第一个能被另一个数整除的就是答案
解法一
变量a=输入[0]
变量b=输入[1]
变量c=1
while ( 变量c<=变量a ){
变量d=变量b*变量c
if ( 变量d%变量a==0 ){
return 变量d
}
变量c+=1
}
return 变量d
解法二(用上一题得到的最大公约数,利用小学二年级就学过的:两数乘积 = 最大公约数 × 最小公倍数来求解)
变量a=输入[0]
变量b=输入[1]
while ( 变量b!=0 ){
变量c=变量a%变量b
变量a=变量b
变量b=变量c
}
return 输入[0]*输入[1]/变量a
5. 斐波那契数列
和第二关上楼梯一样的解法
变量a=输入
变量b=[0,1]
变量c=1
while ( 变量c<变量a ){
变量d=变量b[变量c-1]+变量b[变量c]
变量b.push( 变量d )
变量c+=1
}
return 变量b[变量a]
6. 数字根
还记得入门第14关吗?复制过来就好了,数字之和大于9的话,再加一次。
解法一
变量a=输入
while ( 变量a>9 ){
变量b=0
while ( 变量a>0 ){
变量b+=变量a%10
变量a=Math.floor(变量a/10)
}
变量a=变量b
}
return 变量a
解法二(公式法秒了,注意排除0的情况。有人老老实实两层循环拆位求和,有人掏出一行公式潇洒不羁。两种解法都能过,两种快乐都真实XD)
变量a=输入
if ( 变量a==0 ) return 0
return 1+(变量a-1)%9
7. 最大值
不像是这个难度的关卡![[表情_思考]](https://img.tapimg.com/market/images/b619f76842238d6eb4d2f51733ac8ad3.png)
![[表情_思考]](https://img.tapimg.com/market/images/b619f76842238d6eb4d2f51733ac8ad3.png)
解法一
变量a=输入[0]
变量b=输入[1]
if ( 变量a>变量b ){
return 变量a
}
return 变量b
解法二(利用数组扩展运算符,可以用max函数获取数组里数值最大的元素)
return Math.max(...输入)
8. 和
解法一(下标遍历,循环累加)
变量a=输入
变量b=0
变量c=0
while ( 变量c<变量a.length ){
变量b+=变量a[变量c]
变量c+=1
}
return 变量b
解法二(咱们虽然不方便用到for循环,但还有ForEach可以用,把数组里每一个元素都拎出来)
变量a=0
输入.forEach((变量b)=>变量a+=变量b)
return 变量a
解法三(逼格更高的reduce)
return 输入.reduce((a,b)=>a+b)
9. 罗马数字
两组平行数组用作查表,indexOf查找索引值。从右到左遍历,只要左边小于右边的,就取负值。举个例子,XIV,从右往左,下标从2减到0,就是+5,-1,+10,加起来就是14。
str=输入
chr=['I','V','X','L','C','D','M']
num=[1,5,10,50,100,500,1000]
result=0
right=0
i=str.length-1
while ( i>=0 ){
left=num[chr.indexOf(str[i])]
if ( left<right ){
result-=left
} else {
result+=left
}
right=left
i-=1
}
return result
10. 有效括号
这里提供的一个思路是用'{[(.)]}'.indexOf赋予括号匹配的正负值,遍历到左括号先放进数组里(push),遍历到右括号就开始判断能否和最后一个左括号匹配,匹配就将左括号移出数组(pop)。最后字符串遍历完成,所有左括号都一一匹配消除后,数组清空就表明括号有效
解法一
变量a=输入
变量b=[]
变量c=0
while ( 变量c<变量a.length ){
变量d='{[(.)]}'.indexOf(变量a[变量c])-3
if ( 变量d<0 ){
变量b.push( 变量d )
} else {
if ( 变量b.length==0 ){
return false
}
变量e=变量b.pop( )
if ( 变量d+变量e!=0 ){
return false
}
}
变量c+=1
}
return 变量b.length==0
解法二(还记得入门第17关正则解法吗?这里也可以用到。因为是成对替换,所以只需要循环长度一半的次数)
变量a=输入
变量b=变量a.length
变量c=0
while ( 变量c<=变量b/2 ){
变量a=变量a.replace(/\(\)|\[\]|\{\}/g, '')
变量c+=1
}
return 变量a.length==0
11. 合并有序数组
手搭双指针归并排序,变量d和变量e分别是两个数组的当前遍历索引值,只要一个指针到数组尾了,就跳出遍历循环,最后用slice函数截取指针之后剩余的元素,加到合并数组的末尾。
变量a=输入[0]
变量b=输入[1]
变量c=[]
变量d=0
变量e=0
while ( 变量d<变量a.length
&&变量e<变量b.length ){
if (变量a[变量d]<变量b[变量e]){
变量c.push(变量a[变量d])
变量d+=1
} else {
变量c.push(变量b[变量e])
变量e+=1
}
}
变量c=[...变量c,...变量a.slice(变量d),
...变量b.slice(变量e)]
return 变量c
12. 岛屿数量
深度优先搜索,沉岛解法。把连成片的1都变0。这里函数调用自身递归,bj 里调 bj,四个方向扩散出去,把所有相连的1全部标记成0。这就是“沉岛”——一座岛,遍历一遍,全部淹掉,下次再也不碰。
变量a=输入
变量b=变量a.length
变量c=0
function bj(变量d,变量e){
if ( 变量d<0||变量d>=变量b ){
return
}
if ( 变量e<0||变量e>=变量b ){
return
}
if ( 变量a[变量d][变量e]!=1 ){
return
}
变量a[变量d][变量e]=0
bj(变量d-1,变量e)
bj(变量d+1,变量e)
bj(变量d,变量e-1)
bj(变量d,变量e+1)
}
变量f=0
while ( 变量f<变量b ){
变量g=0
while ( 变量g<变量b ){
if ( 变量a[变量f][变量g]==1 ){
变量c+=1
bj(变量f,变量g)
}
变量g+=1
}
变量f+=1
}
return 变量c
13. 两数之和
暴力枚举,两层循环,外层固定一个数,内层往后找有没有能凑成目标值的。注意目标值写的是输入[1][0]——意思是测试用例的格式是 [数组, [目标值]],第二层套了个数组。这游戏测试用例的格式经常有点怪,习惯就好
变量a=输入[0]
变量b=输入[1][0]
变量c=0
while ( 变量c<变量a.length ){
变量e=变量b-变量a[变量c]
变量d=变量c+1
while ( 变量d<变量a.length ){
if ( 变量e==变量a[变量d]) {
return [变量c,变量d]
}
变量d+=1
}
变量c+=1
}
return [-1,-1]
14. 加一
模拟进位,从右往左找,是9变0再继续,不是9的数加1就输出,全是9就在前头加个元素1
变量a=输入
变量b=变量a.length-1
while ( 变量b>=0 ){
if ( 变量a[变量b]<9 ){
变量a[变量b]+=1
return 变量a
} else {
变量a[变量b]=0
}
变量b-=1
}
return [1,...变量a]
15. 旋转测试
shift函数跟pop类似,一个取头一个取尾。取头push到最后就完成了一次旋转。
解法一
变量a=输入[0]
变量b=输入[1]
变量c=变量a.split( '' )
变量d=0
while ( 变量d<变量a.length ){
变量c.push( 变量c.shift() )
if ( 变量c.join('')==变量b ){
return true
}
变量d+=1
}
return false
解法二(
一行秒了,B要是A的旋转,B就得是A+A的子串,这里也可以手敲includes )
一行秒了,B要是A的旋转,B就得是A+A的子串,这里也可以手敲includes )return (输入[0]+输入[0]).indexOf(输入[1])!=-1
16. 二进制
循环倒取余除以2。注意负数的情况,先把负号存起来,截掉后和正数一样处理方法
解法一
变量a=输入
if ( 变量a==0 ){
return '0'
}
变量b=''
if ( 变量a<0 ){
变量a=-变量a
变量b='-'
}
变量c=''
while ( 变量a>0 ){
变量c=变量a%2+变量c
变量a=Math.floor( 变量a/2 )
}
return 变量b+变量c
解法二(手敲toString,2表示二进制)
return 输入.toString(2)
17. 移动零
经典的双指针技巧。不必新建数组,原地操作。解构赋值[a, b] = [c, d]直接交换零的位置
解法一
变量a=输入
变量b=0
变量c=0
while (变量c<变量a.length){
if (变量a[变量c]!=0){
[变量a[变量b],变量a[变量c]]
=[变量a[变量c],变量a[变量b]]
变量b+=1
}
变量c+=1
}
return 变量a
解法二(利用数组的filter函数过滤元素,再用扩展运算符将非零元素和零组合起来)
return [...输入.filter(n=>n!=0)
,...输入.filter(n=>n==0)]
18. 小偷
forEach 遍历数组,解构赋值[a, b] = [c, d],实现和用数组动态规划状态转移一样的效果。变量b是偷上一家的最大金额,变量c是不偷上一家的最大金额,新 变量b = 旧 变量c,就是上轮的不偷状态变成这轮的偷上一家状态。
变量a=输入
变量b=0,变量c=0
变量a.forEach(( 变量d )=>{
[变量b,变量c]=[变量c,Math.max(
变量c,变量b+Math.max(0,变量d))]
})
return 变量c
普通难度你通过!脑子有没有被重构了?


![[表情_比心]](https://img.tapimg.com/market/images/a272560c8c816575cd8af72d0df6bbf1.png)