首页 > 其他分享 >《剑指offer》day08

《剑指offer》day08

时间:2022-10-14 12:34:27浏览次数:53  
标签:day08 offer int 复杂度 maxProfit prices 动态 public

斐波那契数列

题目描述

image

思路

动态规划+哈希表+递归

动态规划

维基百科定义:

动态规划(英语:Dynamic programming,简称 DP),是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题最优子结构性质的问题。

最核心思想

拆分子问题+记住过往+避免重复计算

避免重复计算可以用哈希表,前提是有重复计算

典型特征

最优子结构、状态转移方程、边界、重叠子问题

  • f(n-1)和f(n-2) 称为 f(n) 的最优子结构
  • f(n)= f(n-1)+f(n-2)就称为状态转移方程
  • f(1) = 1, f(2) = 2 就是边界啦
  • 比如f(10)= f(9)+f(8),f(9) = f(8) + f(7) ,f(8)就是重叠子问题。

每层递归返回f(n-1)+f(n-2),并且取余后加入哈希表中备忘

取余也是有分配律的,并且多次取余都是同一个结果

并且一定要在计算得到结果之前取余,不然会越界

特殊点0和1根据题目处理

动态规划+自底向上

从底往上求,直到抵达需要求的数为止

这种方法就没必要用哈希表来避免重复计算了,不断累加即可

代码实现

动态规划+哈希表+递归

class Solution {
    HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
    public int fib(int n) {
        if(n<2){
            return n;
        }
        if(!map.containsKey(n)){
            int num=fib(n-1)+fib(n-2);
            map.put(n,num%1000000007);
        }
        return (map.get(n));

    }
}

动态规划+自底向上

class Solution {
    public int fib(int n) {
        if(n<2){
            return n;
        }
        int a=0,b=1;
        int cur=2;
        int result=0;
        while(cur<=n){
            result=(a+b)%1000000007;
            a=b;
            b=result;
			cur++;
        }
        return result;

    }
}

复杂度分析

时间复杂度

二者均为O(N)

空间复杂度

用哈希表的为O(N),不用的为O(1)

反思不足

思路

使用自下而上时,没意识到根本不需要保存较早的值,直接往后推,求和即可。下次遇到动态规划的问题可以多想一下这个问题

审题

没看到题目要求,答案要取模

要取余没能想到运算过程中也可能造成越界,只能在运算过程中取余

青蛙跳台阶问题

题目描述

image

思路

同斐波那契数列

求多少种可能性的,并且告诉了边界的,大概率是有递推性质的

本题中状态转移方程的理解,根据最后一步跳的阶数来切入,如果为1,则有f(n-1)种,为n,则有f(n-2)种,加起来即可

  • f(n-1)和f(n-2) 称为 f(n) 的最优子结构
  • f(n)= f(n-1)+f(n-2)就称为状态转移方程
  • f(1) = 1, f(2) = 2,f(0)=1 就是边界啦
  • 比如f(10)= f(9)+f(8),f(9) = f(8) + f(7) ,f(8)就是重叠子问题。

代码实现

动态规划+自底向上

class Solution {
    public int numWays(int n) {
        if(n==0){
            return 1;
        }
        if(n<=2){
            return n;
        }
        int cur=3;
        int a=2,b=1;
        int result=0;
        while(cur<=n){
            result=(a+b)%1000000007;
            b=a;
            a=result;
            cur++;
        }
        return result;
        
    }
}

复杂度分析

时间复杂度

同斐波那契数列

空间复杂度

同斐波那契数列

反思不足

思路

没能想出来状态转移方程

股票的最大利润

题目描述

image

思路

这类最大利润的题,通常都是要往动态规划的角度去向

动态规划+自底向上

  • 状态转移方程:

    maxProfit(n)=max(price(n)-minPrice(n),maxProfit(n-1))

    minPrice(n)=min(price(n),minPrcie(n-1))

  • 最优子结构:

    maxProfit(n-1)、minPrcie(n-1)

  • 边界:

    maxProfit(0)、minPrice(0)

  • 重叠子元素:

动态规划+递归

代码实现

动态规划+自底向上

class Solution {
    public int maxProfit(int[] prices) {
        //如果我们改一下初值,就可以避免这一步判断,然后就超过100%了
        if(prices.length==0){
            return 0;
        }
        //过去的最小价格
        int lPrice=prices[0];
        //过去的最大利润
        int mProfit=0;
        for(int i=1;i<prices.length;i++){//数组的for循环遍历有点不熟悉啊
            lPrice=prices[i]<lPrice ? prices[i]:lPrice;
            mProfit=prices[i]-lPrice>mProfit ? prices[i]-lPrice:mProfit;
        }
        return mProfit;
    }
}
class Solution {
    public int maxProfit(int[] prices) {
        //如果我们改一下初值,就可以避免这一步判断

        //过去的最小价格
        int lPrice=Integer.MAX_VALUE;
        //过去的最大利润
        int mProfit=0;
        for(int i=0;i<prices.length;i++){//数组的for循环遍历有点不熟悉啊
            lPrice=Math.min(lPrice,prices[i]);
            mProfit=Math.max(mProfit,prices[i]-lPrice);
        }
        return mProfit;
    }
}
class Solution {
    public int maxProfit(int[] prices) {
        int cost = Integer.MAX_VALUE, profit = 0;
        for(int price : prices) {
            //这里三元运算符更好,空间复杂度更低
            cost = Math.min(cost, price);
            profit = Math.max(profit, price - cost);
        }
        return profit;
    }
}

动态规划+递归

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length==0){
            return 0;
        }
        return r(prices,1,prices[0],0);

    }
    public int r(int[]prices,int i,int l,int m){
        
        int result=0;
        if(i<prices.length){
            l=prices[i]<l?prices[i]:l;
            m=prices[i]-l>m?prices[i]-l:m;
            result=r(prices,i+1,l,m);

        }else{
            result=m;
        }
        return result;
    }
}

复杂度分析

时间复杂度

均为O(N)

空间复杂度

递归O(N),其他O(1)

反思不足

思路

刚开始理不清思路,知道这类题可以用动态规划,但是没分析出状态转化方程,要理解记住这类求利润题的状态转换方程

java se

Math

Math.min()返回两者之间的最小值

Math.max()返回两者之间的最大值

Integer

Integer.MAX_VALUE整数上限

标签:day08,offer,int,复杂度,maxProfit,prices,动态,public
From: https://www.cnblogs.com/zhouj-learn/p/16791231.html

相关文章

  • 剑指 Offer 05. 替换空格
    请实现一个函数,把字符串 s 中的每个空格替换成"%20"。classSolution{public:stringreplaceSpace(strings){intlen=s.size();intcoun......
  • 剑指offer 38. 字符串的排列
    输入一个字符串,打印出该字符串中字符的所有排列。你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。示例:输入:s="abc"输出:["abc","acb","bac","bca","cab","......
  • 剑指 Offer 22. 链表中倒数第k个节点
    题目描述:输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的......
  • 剑指Offer03.数组中重复的数字
    1.题目描述找出数组中重复的数字。在一个长度为n的数组nums里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复......
  • 剑指 Offer 35. 复杂链表的复制
    请实现copyRandomList函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个next指针指向下一个节点,还有一个random指针指向链表中的任意节点或者null。思路1:利用......
  • part2-HOT100+剑指Offer
    leetcode:​​https://leetcode-cn.com/problemset/algorithms/​​​类别:热题HOT100easy篇共26道No.21--------------可将滑动窗口作为一个章节来看啦。。。标签:哈希......
  • 《剑指offer》day07
    树的子结构题目描述思路遍历比对遍历每个节点,看看它的子树的开头部分,也可能是一整棵,能不能完全匹配上目标一些要注意的细节:B为空可直接返回false,这是题干,A......
  • 收藏!想要拿到高薪Offer,数据库程序员要知道的几件事儿!
    "IT有得聊”是机械工业出版社旗下IT专业资讯和服务平台,致力于帮助读者在广义的IT领域里,掌握更专业、实用的知识与技能,快速提升职场竞争力。 导语:想找到一份程序员的工作,一......
  • day08 final关键字&面向对象——多态&抽象类、方法&向上、向下转型
    day08final关键字最终的不可更改的特点:1)修饰类,类不能被继承2)修饰方法,方法不能被重写3)修饰成员变量(变为常量),值不能修改,名字大写,声明同时给常量赋值main方法中1)修饰......
  • 《剑指offer》day06
    从上到下打印二叉树题目描述思路队列这个其实是树的基本操作之一,层序遍历,也叫广度优先遍历,可以通过队列的先进先出来实现代码实现/***Definitionforabinary......