最长递增子序列

154 阅读2分钟

二分查找

leetcode

function search(nums: number[], target: number): number {
  let left = 0
  let right = nums.length - 1

  while (left <= right) {
    let mid = ~~((left + right) / 2)
    if (nums[mid] < target) {
      left = mid + 1
    }
    else if (nums[mid] > target) {
      right = mid - 1
    }
    else {
      return mid
    }
  }
  return -1
};

跳跃游戏(贪心算法)

思路: 

  • 贪心算法
  • 什么是贪心算法: 局部最优 --推导-> 全局最优
  • 每条一下就更新自己能跳的最远位置

LeetCode

function canJump(nums: number[]): boolean {
    let maxIndex=0
    for(let i=0; i<=nums.length; i++) {
        if(i<=maxIndex) { // 不能超过能跳最远位置
            maxIndex = Math.max(maxIndex, i+nums[i]) // 每条一下就跟新自己能跳的最远位置
            if(maxIndex >= nums.length-1) return true
        }
    }
    return false
};

斐波拉契数(动态规划)

leetCode

思路: 

  • 动态规划

  • 动态规划是什么

    • 动态规划就是把一个大问题拆分成很多小问题,
    • 然后将小问题的结果记录下来
    • 最后通过这些记录推导出最终解
  • 例如: 求fib(5)

    • 需要求出 fib(4) fib(3) fib(2) fib(1)
    • 我们将 fib(4) fib(3) fib(2) fib(1) return的结果记录到 res=[0, 1, 2, 3] 中
    • fib(5) = res[4] + res[3]
  • const mod = Math.pow(10,9)+7 是什么

    • 大数越界
    • 随着n增大,f(n)会超过Int32甚至Int64的取值范围,导致最终的返回值错误。
// 为什么要求答案对 1e9+7 取模
// 大数求余原因:
// 大数越界 
// 大数越界:
// 随着n增大,f(n)会超过Int32甚至Int64的取值范围,导致最终的返回值错误。
const mod = Math.pow(10,9)+7

function fib(n: number): number {
    const res = [0,1] // 已知斐波拉契开头前两位是 0, 1
    for(let i=2; i<=n; i++) {
        res[i] = (res[i-1] + res[i-2]) % mod
    }
    return res[n]
};

最长递增子序列

什么是最长递增子序列

const a = [9, 1,2,3,4,3] // 的最长子序列是 1,2,3,4
const b = [0, 9, 3, 7, 2] // 最长子序列为0, 3, 7

思路

LeetCode

抽象公式

res2 = cp(res1, 1)

res1 = [
    [2],
    [2, 3]
]

res2 = [
    [1],
    [2, 3],
]

遍历到2

arr[2, 3, 1, 5, 4]
res = [
    [2]
]

遍历到3

arr[2, 3, 1, 5, 4]
res = [
    [2],
    [2, 3]
]

遍历到1

arr[2, 3, 1, 5, 4]
res = [
    [1],
    [2, 3],
]

遍历到5

arr[2, 3, 1, 5, 4]
res = [
    [1],
    [2, 3],
    [2, 3, 5],
]

遍历到4

arr[2, 3, 1, 5, 4]
res = [
    [1],
    [2, 3],
    [2, 3, 4],
]

实现

const arrInput = [2,3,1,5,6,8,7,9,4]
const res = lengthOfLIS(arrInput)
console.log(res)

function lengthOfLIS(list) {
    const dp = [
        [list[0]]
    ]

    for(let i=1; i<list.length;i++) {
        const num = list[i]
        updateDp(num)
    }

    return dp[dp.length-1]

    function updateDp(num: number) {
        const index = find(num)
        if(index===0) {
            dp[0]=[num]
        }
        else{
            dp[index] = [...dp[index-1], num]
        }
    }
    // 可使用二分查找优化
    function find(num: number) {
        for(let i=0; i<dp.length; i++) {
            const arr = dp[i]
            const n = arr[arr.length-1]
            if(n>=num) return i
        }
        return dp.length
    }

}