算法-动态规划

511 阅读1分钟

动态规划

我自己的理解,核心是贪心策略,其结果依赖于前一步操作或者其子结构 其主要思路就是找到最优子结构

斐波拉契数列

先来看看一个简单的斐波拉契数列 1 1 2 3 5 8......比如求第n个数数值,需要知道n-1个和n-2个,n从0开始

    function Fib(n){
        if(n<2) return 1
        else return Fib(n-1)+Fib(n-2)
    }

但是递归的操作很多时候会非常的浪费内存,可能会出现栈溢出的情况 所以可以采用非递归的方式来进行实现斐波拉契数列

    function Fib(n){
        if(n<2) return 1
        var preone=1
        var pretow=1
        var res=0
        for(let i=2;i<=n;i++){
            res=preone+pretwo
            pretwo=preone
            preone=res
        }
        return res
    }

青蛙跳台问题

一只青蛙一次跳上1级台阶,也可以跳上2级台阶,求该青蛙跳上n级台阶有多少种跳法

思路:逆向思维,最后一跳可能跳一级也可以跳两级,所以在跳n级的最后一跳由Func(n-1)+ Func(n-2)

这不就是斐波拉契数列吗(1,1,2,3)

    function Fib(n){
    //n==0的时候只有一种跳法,n==1的时候也只有一种跳法
        if(n<2) return 1
        let preone = 1
        let pretwo = 1
        let res=0
        for(let i=2;i<=n;i++){
            res=preone+pretwo
            pretwo = preone
            preone = res
        }
        return res
    }

股票最大利润

假如把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少 示例

输入: [7,1,5,3,6,4]

输出: 5

股票最大收益问题是一个比较经典的动态规划问题 我们用dp=[]存放当前以及前面所有天数中所能够获取的最大收益 dp需要初始化,因为dp[i]取决于d[i-1] dp[0]=0,第一天只能买入不能卖出,所以收益为0

    function maxProfit(arr){
        if(arr.length<2) return 0
        var dp=[]
        dp[0]=0
        mincost=arr[0]//记录当前最小的成本(即买入价格)
        for(let i=1;i<arr.length;i++){
            dp[i]=Math.max(dp[i-1],arr[i]-mincost)
            mincost = Math.min(mincost,arr[i])
        }
        return dp[arr.length-1]
    }

礼物最大价值

在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?

这个题目可以拓展成很多种,但是其核心思路就是求最小权值和或者最大权值和 这属于二维的动态规划 初始化dp=[][] dp[0][0]=grid[0][0]

    function maxGiftValue(grid){
        let m=grid.length//行数
        let n=grid[0].length//列数
        var dp=[]
        for(let i=0;i<m;i++){
            dp.push([])
            for(let j=0;j<n;j++){
                if(i==0&&j==0) dp[i][j]=grid[i][j]
                else if(i==0&&j!=0) dp[i][j]=dp[i][j-1]+grid[i][j]
                else if(i!=0&&j==0) dp[i][j]=dp[i-1][j]+grid[i][j]
                else dp[i][j]=Math.max(dp[i][j-1],dp[i-1][j])+grid[i][j]
            }
        }
        return dp[m-1][n-1]
        
    }

最长不含重复字符的子字符串

请从字符串中找出一个最长的不包含重复字符串的子字符串,计算该最长子字符串的长度 采用滑动窗口,双指针控制滑动窗口大小

    function lengthOfLongestSubstring(str){
        let map = new Map()
        let left = 0
        let right = 0
        let res = 0
        while(right<str.length){
            let cur = str[right]
            if(map.get(cur)>=0){
                left = Math.max(left,map.get(cur)+1)
            }
            map.set(cur,right)
            res = Math.max(res,right-left+1)
            right++
        }
        return res
        
    }