873. Length of Longest Fibonacci Subsequence [JavaScript]

这是一篇关于寻找数组中最长斐波那契子序列的解题文章,重点讲述了两种方法:一种是通过记录元素存在的对象来判断,另一种是使用动态规划。文章提供了JavaScript代码实现,并提到所给数组是递增的。作者鼓励读者留言讨论,并分享了个人的LeetCode刷题之旅。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、解题思路

  本题要求找出数组中满足斐波拉契特点的最长序列,并且所给点的数组是一个递增数组,这一条件非常的重要。

  第一种方法:通过记录数组中元素存在的对象判断每两个数字能够形成的最长序列。

const lenLongestFibSubseq = A => {
  const max = A.length
  if (max < 3) {
    return 0
  }

  const hash = {}

  for (let i = 0; i < max; i++) {
    hash[A[i]] = true
  }

  let ans = 0

  for (let i = 0; i < max - 1; i++) {
    for (let j = i + 1; j < max; j++) {
      ans = Math.max(ans, findFib(A[i], A[j]))
    }
  }
  return ans

  function findFib (a, b) {
    let size = 0
    let result = [a, b]
    while (hash[a + b]) {
      [a, b] = [b, a + b]
      size += size === 0 ? 3 : 1
    }
    return size
  }
}

  上述方法的时间复杂度为O(n^3),空间复杂度为O(n)。

  第二方法是采用动态规划来处理。

  定义状态:

  dp[i][j]表示以第i个字符第j个字符结尾所形成序列的长度。

  当拥有i和j两个元素后,实际上就需要找出A[j]-A[i]是否存在于数组,并且它的下标应该小于i,所以状态转移方程为:

  A[j] - A[i] === A[k] && A[k] in A && k < i
  ==> dp[i][j] = (dp[index][i] || 0) + 1

  这样时间复杂度为O(n2),并且空间复杂度也为O(n2),具体代码如下:

二、代码实现

const lenLongestFibSubseq = A => {
  const max = A.length
  if (max < 3) {
    return 0
  }

  const cache = {}

  let dp = []
  let ans = 0
  // 记录每个数字的下标
  for (let i = 0; i < max; i++) {
    dp[i] = []
    cache[A[i]] = i
  }

  for (let i = 1; i < max - 1; i++) {
    for (let j = i + 1; j < max; j++) {
      const rest = A[j] - A[i]
      const index = cache[rest]
      if (index !== undefined && index < i) {
        dp[i][j] = (dp[index][i] || 0) + 1
        ans = Math.max(dp[i][j], ans)
      }
    }
  }

  return (ans === 0 ? ans : ans + 2)
}

  如果本文对您有帮助,欢迎关注微信公众号,为您推送更多大前端相关的内容, 欢迎留言讨论,ε=ε=ε=┏(゜ロ゜;)┛。

  您还可以在这些地方找到我:

这段代码是一个区块链的实现中的获取最长链的函数,其主要思路是遍历所有区块,从每个区块出发,向前查找每个区块的前一个区块是否在当前区块链中存在,并且不是根节点'root'。如果找到了前一个区块,则将其加入到当前链表的头部。最终,如果当前链表的长度大于已经找到的最长链长度,则将当前链表作为最长链。 这个函数可能需要一些解释,下面是对代码每行的解释: 1. `longestChain () {`: 定义一个函数叫做`longestChain`。 2. `let longestChain = [];`: 初始化一个最长链为空数组。 3. `for (const [hash, block] of this.blocks) {`: 遍历所有区块,使用解构赋值获取当前区块的哈希值和区块本身。 4. `const chain = [block];`: 初始化一个当前链表,将当前区块加入其中。 5. `let previousBlock = block;`: 初始化一个前一个区块,将其赋值为当前区块。 6. `while (this.blocks.has(previousBlock.previousHash) && (this.blocks.has(previousBlock.previousHash)).has !== 'root') {`: 在当前区块链中查找前一个区块,如果找到且前一个区块不是根节点'root',则进入循环。 7. `previousBlock = this.blocks.get(previousBlock.previousHash);`: 将前一个区块作为当前区块,继续向前查找。 8. `chain.unshift(previousBlock);`: 将前一个区块加入到当前链表的头部。 9. `if (chain.length > longestChain.length) {`: 判断当前链表是否比已经找到的最长链更长。 10. `longestChain = chain;`: 如果当前链表更长,则将其作为最长链。 11. `console.log(longestChain)`: 输出最长链到控制台。 12. `return longestChain;`: 返回最长链。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值