leetcode Hot100 之爬楼梯、斐波那契数列、两数之和

780 阅读2分钟

前言

学习一下算法题吧

一、爬楼梯

爬楼梯的leetcode地址

题目描述 image.png 思路发现

爬楼梯这道题,通过读题,发现它和初中高中的数学题里的规律推导题类似,要发现它的计算格式
当n=1时, f(n) = 1
当n=2时, f(n) = 2
当n=3 时, f(n) = 3
当n = 4 时, f(n) = 5
……依此类推得到

f(n) f(n)

image.png

1、 递归解法

递归的关键是递归的出口条件,分基线条件终止条件,如果没设置好出口,将出现是循环的情况,就像俄罗斯套娃一样。
像上面公式的f(1) =1,f(2)=2就是基线条件
如果,再给函数一个设定,最多递归20次,超过20次就终止,这就是终止条件

由上面推导格式,使用递归方式解题应该是比较简明的方法。

let climbStairs = function(n) { 
    if(n == 1) return 1;
    if(n== 2 ) return 2; 
    return climbStairs(n-1)+climbStairs(n-2);
};

这样的解法,看上去简单清晰,但是它进行了大量的重复计算,容易造成时间复杂度的增加,不信你看它就超时了。

image.png

为什么说会有重复计算你,看下图,由颜色的就是重复计算的地方 image.png

2、 递归优化解法

考虑时间复杂度,我们可以对上面的做法进行优化,将每次计算的值用Map对象存起来。这样如果下一轮计算的时候,map.get(n) 有值就可以直接返回,而不用进行重复的计算。

/**
 * @param {number} n
 * @return {number}
 */
let map = new Map()
let climbStairs = function(n) {
 
 if(n == 1) return 1;
 if(n== 2 ) return 2;
 if(map.get(n) != null) return map.get(n)
 else{
    let result = climbStairs(n-1)+climbStairs(n-2)
    map.set(n,result)
    return result;
 }
};

这样时间复杂度就是O(n)了

3、 循环解法

一切可以用递归方法解决的题,都可以用迭代循环的方式来解决,循环的方式就多声明三个变量来进行替换和累加。

/**
 * @param {number} n
 * @return {number}
 */
 let climbStairs = function(n) {
  if(n==1) return 1;
  if(n==2) return 2;
  let result = 0, first = 1, second =2;
  for(let i = 3;i <=n ;++i){
     result = first + second;
     first = second;
     second = result;
  }
  return result;
 };

4、 数组方式的循环解法

利用数组存值的特性,也是用循环叠加的方式,不过这样空间复杂度会是O(n),上面几种空间复杂度是O(1).

let climbStairs = function (n) {
  const memo = [];
  memo[1] = 1;
  memo[2] = 2;
  for (let i = 3; i <= n; i++) {
    memo[i] = memo[i - 1] + memo[i - 2];
  }

  return memo[n];
};

以上是爬楼梯的四种解题方法,可能会有其他解题的方法,到这里我们大概学习了递归的关键是公式推导和设置递归出口,可以设置缓存减少重复计算,可以利用数组的一些方法特点来存值。

二、斐波那契数列

题目描述

image.png 解题思路 这题和爬楼梯是类似的,甚至它还给出了解题函数方程,不过有个最大值条件,答案需要取模

1、 递归解法

在笔试题中,可能会这样去写,不过时间复杂度高,而且在这道题中有限制答案要取模

**
 * @param {number} n
 * @return {number}
 */
 let fib = function(n) {
  if(n==0) return 0
  if(n==1) return 1
  return fib(n-1) + fib(n-2)
 };

2、 循环解法

这样才是比较正确的做法。

/**
* @param {number} n
* @return {number}
*/
let fib = function (n) {
  const MOD = 1000000007;
  if (n == 0) return 0
  if (n == 1) return 1
  let result = 0, first = 0, second = 1;
  for (let i = 2; i <= n; ++i) {
    result = (first + second) % MOD;
    first = second;
    second = result
  }
  return result;
};

三、两数之和

题目描述

image.png

1、暴力求解

直接暴力的做法就是循环嵌套找出结果,像这样子,时间复杂度为O(n^2)

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let result = [];
    for(let i = 0; i< nums.length; i++) {
        for(let j = i + 1; j < nums.length; j++){
            if(nums[i] + nums[j] == target){
                result[0] = i;
                result[1] = j;
                return result;
            }
        }
    }
    return result;
};

定义一个数组来保存原数组的两个值的下标两次循环嵌套,在通过if(nums[i] + nums[j] == target)找出对应的两个值与目标值target相等,然后返回数组下标,

2、使用Map对象优化

JavaScript中的Map对象就是和Java中HashMap对象是一样的,通用是使用缓存策略来降低重复计算,达到降低时间复杂度的作用。像下面这样时间复杂度就是O(n)

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let map = new Map()
    let result = [];
    for(let i = 0; i< nums.length; i++) {
     let another = target - nums[i]
     let anotherIndex = map.get(another)
     if(anotherIndex != null) {
        result[0] = anotherIndex
        result[1] = i
        break
     }else{
        map.set(nums[i], i);
     }
    }
    return result;
};

我们定义了map 对象进行计算缓存,将nums数组对应的值作为map 的key,数组的下标数为map对象的的value

例如: nums = [2,8,6,9], target= 11;
那么第一轮i=0: another = 9, anotherIndex = map.get(9) = null, 进入else ,此时 map= {2=>0}
那么第二轮i=1: another = 3, anotherIndex = map.get(3) = null, 进入else ,此时 map= {2=>0,8=>1}
那么第三轮i=2: another = 5, anotherIndex = map.get(5) = null, 进入else ,此时 map= {2=>0,8=>16=>2}
那么第四轮i=3: another = 2, anotherIndex = map.get(2) = 0, 进入if ,此时 map= {2=>0,8=>16=>2}

结果返回 [0,3]

总结

以上是三道简单级的leetcode Hot100, 主要用到了递归计算缓存策略用到map对象,通过缓存计算结果,降低时间复杂度

往期优质文章推荐 Vue3+Vite+TS基于Element plus 二次封装业务组件(含Vue3知识点)

bonbon-nft-auction-platforms-art-games-video-music.png