常用算法

128 阅读1分钟

爬台阶

  • 假如你在爬台阶,需要n阶才能到达楼顶,每次可以爬1或2个台阶,有多少种不同的方式爬到楼顶;
  • n一定为正整数;
  • 可以把总台阶分为两部分,即将要爬的一步,和这一步爬完之后剩余的台阶;每次可以选择爬1或2阶,知道剩余的台阶数为0,终止;
function climb(n) {

  if(n === 0) return 1

  climb(n - 1) // 爬1阶后爬剩余的台阶

  if(n -2 >=0){

    climb(n -2) // 爬2阶后爬剩余的台阶 这时候要判断剩余台阶数是不是大于等于2

  }

}

  


//改进一下,终止条件为 n <= 2

function climb(n) {

  if(n <= 0) return 0

  if(n <=2) return n

  return climb(n-1) + climb(n-2)

}

  


//此时可以发现climb(n -1) 内部又调用了climb(n - 2) ,climb(n)也调用了climb(n-2)

//保存一下结果

let cache = {}

function clinmb(n) {

  if (n <= 0) return 0    // 直接终止

  if (n <= 2) return n    // 剩余1阶有一种解法 2阶有两种解法

  if (cache[n]) return cache[n]

  return cache[n] = climb(n - 1) + climb(n - 2)

}

斐波那契数列

  • 首项为0, 第二项为1,... 第n项为n-1和第n-2项之和
//1,使用循环

function fibonacci(n) {

  if(n <= 2) return n-1

  let n1 = 0, n2 = 1

  //从下标为2 处开始(即第三项)

  for(let i = 2; i < n; i++) {

    //每一项的计算都是从第一项开始加,n1和 n2这两个临时变量每次都存放最新的两个值,其中n2这个变量存放前两项之和

    [n1, n2] = [n2, n1 + n2]

  }

  return n2

}

  


//2, 使用递归

//每次求值都要进行完整的递归,很消耗内存空间

function fibonacci(n) {

  return n <= 2 ? n-1 : fibonacci(n-1) + fibonacci(n-2)

}

  


//可以设置缓存,假如所求的值已经存储起来了,直接在内存里获取

//throw new Error();   这个是创建错误,创造一个错误类型抛出

//throw error   这个是抛出错误。

  


let cache = {}

function fibonacci(n) {

  if(n<0) throw new Error("输入数字不能小于0")

  if(n <= 2) return n-1

  if(cache[n]) return cache[n]

  return cache[n] = fibonacci(n -1) + fibonacci(n -2)

}

汉诺塔问题

  • 汉诺塔问题指的是:将一个柱子中的所有圆盘移动到另一个柱子,移动过程需遵守以下规则:每次只能移动一个圆盘,而且只能移动某个柱子上最顶部的圆盘;移动过程中,必须保证每个柱子上的大圆盘都位于小圆盘的下面;
  • 加入有三个桩A,B,C,初始盘子在A桩上,移动完成后盘子在C桩上;
  • 当n == 1时,直接将盘子从A 移动到C;
  • 当n > 1时,可以拆分成三个步骤
    • 1,将n-1个盘子从A移动到B;
    • 2,将编号为n的盘子从A移动到C;
    • 3,将n-1个盘子从B移动到C;
  • 在此过程中1,3显然是递归调用
function hanoi(n, current = 'A', temp = 'B', target = 'C') {

  if(n<=0) return 0

  let sum = 1

  sum += hanoi(n-1,current, target, temp)

  console.log(current + ' ---> ' + target)

  sum += hanoi(n - 1, temp, target, current)

  return sum

}