webveuje/考试/原题/js/js递归20210409.md
2021-04-29 17:16:40 +08:00

319 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 递归
## 简答题
1. 九九乘法表
```
function num(nums){
if(nums==1){
console.log("1x1=1")
}else{
num(nums-1)
for(var i=1,str='';i<=nums;i++){
str += `${i}x${nums}=`+i*nums+' '
}
console.log(str)
}
}
num(9)
// 循环
for(var i=1;i<10;i++){
let str = ''
for(var j=1;j<10;j++){
if(i>=j){
str += `${j}x${i}=`+i*j+' '
}
}
console.log(str)
}
```
2. 定义一个函数 实现n的阶乘
```
function jc(n){
if(n<=1){
return 1;
}else{
return n*arguments.callee(n+1);
}
}
```
3. 一只青蛙可以一次跳 1 级台阶或者一次跳 2 级台阶,例如:
跳上第 1 级台阶只有一种跳法:直接跳 1 级即可。 跳上第 2 级台阶有两种跳法:每次跳 1 级,跳
两次;或者一次跳 2 级。 问要跳上第 n 级台阶有多少种跳法?
```
function ge(n){
if(n==0){
return 0;
}else if(n==1){
return 1;
}else if(n==2){
return 2;
}
return ge(n-1)+ge(n-2);
}
```
4. 编写一个函数输入n为偶数时调用函数求1/2+1/4+…+1/n,当输入n为奇数时调用函数求/1+1/3+…+1/n;
```
function num(nums){
if(nums==1){
console.log("1x1=1")
}else{
num(nums-1)
for(var i=1,str='';i<=nums;i++){
str += `${i}x${nums}=`+i*nums+' '
}
console.log(str)
}
}
num(9)
// 循环
for(var i=1;i<10;i++){
let str = ''
for(var j=1;j<10;j++){
if(i>=j){
str += `${j}x${i}=`+i*j+' '
}
}
console.log(str)
}
```
5. 1+2+3+4+....+100(n)求和
```
function dg(x){ //第一题
if(x==1)return 1;
return dg(x-1)+x;
}
var lj=dg(100);
console.log(lj)
```
6. 细胞分裂 有一个细胞 每一个小时分裂一次一次分裂一个子细胞第三个小时后会死亡。那么n个小时候有多少细胞
```
// 每三个小时为一个周期 第四个小时就 go die 了。
// 方法一
// 第一个小时只有a态细胞第二个小时a态细胞分裂原来的a态细胞变成了b态细胞分裂出来的细胞变成了新的a态细胞第三个小时a态细胞继续分裂变成b态细胞和新的a态细胞b态细胞分裂变成c态细胞和a态细胞第四个小时a、b、c态细胞都会分裂并且按照之前的规律转变。得出下面的结论
// a 初始态 一个小时 前一个小时的 a+b+c
// b 幼年态 两个小时 前一个小时的 a
// c 成熟态 三个小时 前一个小时的 b
function allCell(n){
// a态细胞
let aCell = function(n){
if(n==1){
return 1;
}else{
return aCell(n-1)+bCell(n-1)+cCell(n-1);
}
}
// b态细胞
let bCell = function(n){
if(n==1){
return 0;
}else{
return aCell(n-1);
}
}
// c态细胞
let cCell = function(n){
if(n==1||n==2){
return 0;
}else{
return bCell(n-1);
}
}
return aCell(n)+bCell(n)+cCell(n)
}
console.log(allCell(10))
// 方法二
// 这个方法就是分成了 活着的 和 死亡的
function cell(hour){
// 活着的细胞
function livecell(hour){
if(hour<4){
// 前三个小时没有死亡的细胞 成2的n-1次方增长
return Math.pow(2,hour-1)
}else{
// 从第四个小时开始有死亡的细胞
// 活着的细胞 = 前一个小时活着的细胞 - 这个小时死去的细胞
return livecell(hour-1)*2 - diecell(hour)
}
}
// 死亡的细胞
function diecell(hour){
if(hour<4){
// 前三个小时没有死亡的细胞
return 0
}else{
// 因为三个小时一个周期
// 也就是每三个小时,(n-3)时的细胞就会死完
// 那么 这个小时(n)死去的细胞 + 上个小时(n-1)死去的细胞 + 前两个小时(n-2)死去的细胞 = 前三个小时(n-3)活着的细胞
return livecell(hour-3) - diecell(hour-1) - diecell(hour-2)
}
}
return livecell(hour)
}
console.log(cell(10))
```
7. 有 64 个格子第一个格子放一粒麦子第二个放2粒第三个放4粒...每个格子都是前边的两倍。一共有多少粒?
```
let sum = 0
let start = 1;
let end = 0;
function tow(){
if(end>=64){
return false
}
sum+=start
start*=2
end++
tow()
}
tow()
console.log(sum)
```
8. 输出斐波那契数列
```
// 递归
let a = 0;
function tu(num){
a++
if(num==1||num==2){
return 1
}
let nums = tu(num-1)+tu(num-2)
return nums
}
console.log(tu(8),a)
// 闭包解决
// 也就是存在数组中,再次循环时,如果数组中已经存在,就返回数组中的值,大大减少了递归调用函数的次数
var count2=0;
var fiba = (function(){
var arr = [0,1,1]; //第0位只是占位从第一位开始算起
return function(n){
count2++;
var res=arr[n];
if(res){// 如果arr中存在返回这个值
console.log(res,'----')
return res;
}else{
console.log(arr[n],'+++++')
arr[n]=fiba(n-1)+fiba(n-2);
return arr[n];
}
}
})();
console.log(fiba(8),count2)
// 普通
// 普通循环解决这个问题是性能最好的。
let a = 1;
let b = 1
let c;
function tu(num){
for(let i=0;i<num-2;i++){
c = a+b;
a = b;
b = c
}
return c;
}
console.log(tu(8))
```
9.
10. 下面代码导致的问题如何解决
```
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * factorial(num-1);
}
}
var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4));
```
答案
我们知道arguments.callee 是一个指向正在执行的函数的指针,因此可以用它来实现对函数
的递归调用,例如:
```
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * arguments.callee(num-1);
}
}
```
11. 猴子吃桃问题:猴子第一天摘下若干个桃子, 当即吃了一半,还不过瘾,又多吃了一个; 第二天早上又将剩下的桃子吃掉一半,又多吃了一个。
* 以后每天早上都吃了前一天剩下的一半零一个。 到第10天早上想再吃时见只剩下一个桃子了。 求第一天共摘了多少。
程序分析:采取逆向思维的方法,从后往前推断。
// 倒数第1 2 3 4 5 6 天
// 桃数量1 4 10 22 46 94
// 采用递归的方法
```
// 返回第n天的桃子数量
function getValue(n){
if (n == 1) {
return 1;
}
return (getValue(n - 1) + 1) * 2;
}
for (int i = 1; i < 11; i++) {
console.log("" + i + "\t" + getValue(i) + "");
}
```