前言:本系列总结了在前端面试中可能遇到的若干算法题,不按期更新前端
最近看有同窗面试遇到了n阶变态跳问题(n级台阶,每次最多容许跨n步,求多少种跨越方式),下面是一个变种问题面试
f(n,m) = f(n-1,m)+f(n-2,m)+...+f(n-m,m)
当m=2时,这就是一个斐波那契数列。
同时,对于n阶变态跳,即n=m时,用公式有如下特色:
f(n) = f(n-1)+f(n-2)+...+f(1);//①
f(n-1) = f(n-2)+f(n-3)+...+f(1);//②
①-② 即f(n) = 2f(n-1),能够看出n阶变态跳的结果,实际是一个等比数列,也就是f(n) = 2^(n-1)算法
function f(n,m) { var count = 0; if (n == 0) { return 1; } if (n >= m) { for (var i=1; i<=m; i++) { count += f(n-i,m); } }else { count += f(n,n); } return count; }
//首先根据规律,存储前m项结果,当n<m时,有f(n,m)=f(n,n)=f(n)=2^(n-1) //接下来咱们依次计算n=m+1时的结果并存入数组 //根据思路提示,第n项结果等于数组逆序前m项的和,咱们截取数组迭代求和 //最后返回顶层的数据,便是f(n,m) function f(n,m) { var arr = [1]; for (var i=1; i<m;i++) { arr.push(Math.pow(2,i)); } for (var j=m+1; j<=n; j++) { arr.push(arr.slice(-m).reduce((a,b) => a+b)) } return arr.pop(); }
//输入对象 var obj = { a: { b: { c: { d:'h', j:'l', o: { p:'q', r:'s' }, t: 'u' } }, v: { w: { x: { y: 'z' } } } }, e: { f: { i: 'k' }, m: 'n' } } //输出结果,按照层数,把同一层的属性放在同一个子数组内 var result = [[a,e],[b,v,f,m],[c,w,i],[d,j,o,t,x],[p,r,y]];
//输出结果数组 var result = []; //递归层数,也就是属性层数 var num = 0; function getProp(obj) { //获取对象的属性数组 var keys = Object.keys(obj); var len = keys.length; for(var i=0; i<len; i++) { //判断属性值,若是是对象,则递归遍历 if(typeof obj[keys[i]] == 'object') { /若是属性是对象,层数加一 num++; //用result[num-1]存储每一层的结果,若是该层首次存储属性名称,初始化为空数组 if(typeof result[num-1] != 'object') { result[num-1] = []; } result[num-1].push(keys[i]); getProp(obj[keys[i]]); //注意当一层的全部属性都遍历完以后,返回上一层 if(i == len-1) { num--; } }else { //若是属性不是层数,那么先对层数加一,存入后再减一 num++; if(typeof result[num-1] != 'object') { result[num-1] = []; } result[num-1].push(keys[i]); num--; if(i == len-1) { num--; } } } } getProp(obj); console.log(result);