前言:本系列总结了在前端面试中可能遇到的若干算法题,不定期更新
最近看有同学面试遇到了n阶变态跳问题(n级台阶,每次最多允许跨n步,求多少种跨越方式),下面是一个变种问题
题目:假设有n级台阶,每次最多允许跨m步(m<=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)
解法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;
}
解法2:非递归算法
//首先根据规律,存储前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();
}
深度遍历js对象的属性名
题目:给定若干嵌套项的js对象,如下
//输入对象
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);
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。