第 8 天

动态规划(简单)

剑指 Offer 10- I. 斐波那契数列

写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:

F(0) = 0,   F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

示例 1:

输入:n = 2
输出:1

示例 2:

输入:n = 5
输出:5

提示:

  • 0 <= n <= 100

题解思想:动态规划、矩阵快速幂、打表动态规划

动态规划:改写递归即可

class Solution {
int mod = (int)1e9+7;
public int fib(int n) {
if (n <= 1) return n;
int a = 0, b = 1;
for (int i = 2; i <= n; i++) {
int c = a + b;
c %= mod;
a = b;
b = c;
}
return b;
}
}

矩阵快速幂:记熟方法

class Solution {
static final int MOD = 1000000007; public int fib(int n) {
if (n < 2) {
return n;
}
int[][] q = {{1, 1}, {1, 0}};
int[][] res = pow(q, n - 1);
return res[0][0];
} public int[][] pow(int[][] a, int n) {
int[][] ret = {{1, 0}, {0, 1}};
while (n > 0) {
if ((n & 1) == 1) {
ret = multiply(ret, a);
}
n >>= 1;
a = multiply(a, a);
}
return ret;
} public int[][] multiply(int[][] a, int[][] b) {
int[][] c = new int[2][2];
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
c[i][j] = (int) (((long) a[i][0] * b[0][j] + (long) a[i][1] * b[1][j]) % MOD);
}
}
return c;
}
}

打表动态规划:

class Solution {
static int mod = (int) 1e9+7;
static int N = 110;
static int[] cache = new int[N]; public int fib(int n) {
if (n == 0) {
return 0;
}
if (n == 1 || n == 2) {
return 1;
}
if (cache[n] != 0) {
return cache[n];
}
cache[n] = (fib(n - 1) + fib(n - 2)) % mod;
return cache[n];
}
}

剑指 Offer 10- II. 青蛙跳台阶问题

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

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

示例 1:

输入:n = 2
输出:2

示例 2:

输入:n = 7
输出:21

示例 3:

输入:n = 0
输出:1

提示:

  • 0 <= n <= 100

题解思路:动态规划、矩阵快速幂

动态规划:与斐波拉契一样

class Solution {
public int numWays(int n) {
//递归方法 找通项公式
// 将大问题拆分成小问题 n级台阶有 numWays(n-1)+numWays(n-2)
//出口为 n=1 返回1 n=2 返回2
if(n==0||n==1) return 1;
if(n==2) return 2;
int s1=1,s2=2;
int sum;
//最优雅的方式 动态规划 且空间用的也少
for(int i=3;i<n+1;i++){
sum=(s1+s2)%1000000007;
s1=s2;
s2=sum;
}
return s2;
}
}

矩阵快速幂:

class Solution {
private final static int COS = 1000000007;
private int[][] res ={{1,0},{0,1}};
private int[][] temp ={{1,1},{1,0}};
public int numWays(int n) {
int num = fastPow(n);
return num;
} public int fastPow(int n) {
while (n != 0) {
if((n&1) == 1) res = mul(res,temp);
temp = mul(temp,temp);
n = n>>>1;
}
return res[0][0];
} public int[][] mul(int[][] a1, int[][] a2) {
int row = a1.length;
int col = a2[0].length;
int[][] c = new int[row][col];
for (int i=0; i<row; i++) {
for (int j=0; j<col; j++) {
long fac = 0l;
for (int k=0; k<a1[0].length;k++) {
long l1 = a1[i][k];
long l2 = a2[k][j];
fac += (l1*l2)%COS;
}
c[i][j] = (int)fac%COS;
}
}
return c;
}
}

剑指 Offer 63. 股票的最大利润

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

示例 1:

输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。

示例 2:

输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

限制:

0 <= 数组长度 <= 10^5

题解思路:单调栈、动态规划

单调栈:每次记录当前最大值

class Solution {
public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}
Stack<Integer> stack = new Stack<Integer>();
stack.push(prices[0]);
int max = 0;
for (int i = 0; i < prices.length; i ++) {
if (stack.peek() > prices[i]) {
stack.pop();
stack.push(prices[i]);
} else {
max = Math.max(max, prices[i] - stack.peek());
}
}
return max;
}
}

动态规划:维护一个最低价格 cost,判断当前卖出获利是否大于之前卖出获利

class Solution {
public int maxProfit(int[] prices) {
if (prices.length < 2) return 0; // 没有卖出的可能性
// 定义状态,第i天卖出的最大收益
int[] dp = new int[prices.length];
dp[0] = 0; // 初始边界
int cost = prices[0]; // 成本
for (int i = 1; i < prices.length; i++) {
dp[i] = Math.max(dp[i - 1], prices[i] - cost);
// 选择较小的成本买入
cost = Math.min(cost, prices[i]);
} return dp[prices.length - 1];
}
}

剑指 offer 第 8 天的更多相关文章

  1. 剑指Offer面试题:1.实现Singleton模式

    说来惭愧,自己在毕业之前就该好好看看<剑指Offer>这本书的,但是各种原因就是没看,也因此错过了很多机会,后悔莫及.但是后悔是没用的,现在趁还有余力,把这本书好好看一遍,并通过C#通通实 ...

  2. 剑指Offer面试题:14.链表的倒数第k个节点

    PS:这是一道出境率极高的题目,记得去年参加校园招聘时我看到了3次,但是每次写的都不完善. 一.题目:链表的倒数第k个节点 题目:输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的习惯,本题 ...

  3. 《剑指offer》面试题12:打印1到最大的n位数

    面试题12:打印1到最大的n位数 剑指offer题目12,题目如下 输入数字n,按顺序打印出1到最大的n位十进制数,比如输入3,则打印出1,2,3一直到最大的三位数999 方法一 和面试题11< ...

  4. 《剑指offer》面试题11: 数值的整数次方

    面试题11: 数值的整数次方 剑指offer面试题11,题目如下 实现函数double power(double base,int exponent),求base的exponent次方, 不得使用库 ...

  5. 剑指 Offer 题目汇总索引

    剑指 Offer 总目录:(共50道大题) 1. 赋值运算符函数(或应说复制拷贝函数问题) 2. 实现 Singleton 模式 (C#) 3.二维数组中的查找 4.替换空格              ...

  6. 面试题目——《剑指Offer》

    1.把一个字符串转换成整数——<剑指Offer>P29 2.求链表中的倒数第k个结点——<剑指Offer>P30 3.实现Singleton模式——<剑指Offer> ...

  7. 剑指offer习题集2

    1.把数组排成最小的数 class Solution { public: static bool compare(const string& s1, const string& s2) ...

  8. 剑指offer习题集1

    1.打印二叉树 程序很简单,但是其中犯了一个小错误,死活找不到,写代码要注意啊 这里左右子树,要注意是node->left,结果写成root->left vector<int> ...

  9. 剑指Offer:面试题20——顺时针打印矩阵(java实现)

    题目描述: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数 字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1, ...

  10. 牛客网上的剑指offer题目

    题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 题目:请实现一个函数,将一 ...

随机推荐

  1. JS缓存三种方法_sessionStorage_localStorage_Cookie

    1.sessionStorage:临时的会话存储 只要当前的会话窗口未关闭,存储的信息就不会丢失,即便刷新了页面,或者在编辑器中更改了代码,存储的会话信息也不会丢失. 2.localStorage:永 ...

  2. vs2013如何添加扩展库函数

    本文仅针对C和C++ vs2013下载C/C++编译器后,能够包含常见的头文件,stdlib.h,stdio.h,math.h这些.如果有其他需求例如:调用GL/glfw32.h,freeglut.h ...

  3. kubectl工具安装指南

    kubectl是一个用于连接Service Mesh控制平面的工具,可以安装在办公电脑的Windows系统上,也可以安装在虚拟机的Linux系统上,只要网络能与控制平面的公网地址互通即可.下面分别介绍 ...

  4. (论文笔记)Learning Deep Structured Semantic Models for Web Search using Clickthrough Data

    利用点击数据学习web搜索的深度学习模型   [总结] 该模型可以得到query和item的低维度向量表示,也可以得到二者的余弦语义相似度. 学习过程是通过最大化后验概率的极大似然估计得到的参数.   ...

  5. 西瓜书6.2 matlab的libsvm使用

    因为python的教程没有找到详细的所以就改用matlab了 使用的是matlab r2016a,libsvm3-24,具体的安装配置教程就直接参考谦恭大大的了: https://blog.csdn. ...

  6. Openpyxl一些简单的用法

    这个代码是需要自己先建立一个excel.然后导入数据 from openpyxl import load_workbook #按照一个格子输入进去 workbook = load_workbook(r ...

  7. C# POST GET请求方式汇总

    /// <summary> /// POST方式提交 application/json /// </summary> /// <param name="post ...

  8. Linux基础知识2

    目录和文件管理 linux以目录形式挂载(通过目录访问存储设备)文件系统,目录结构分层的树形结构. 链接:在共享文件和访问它的用户的若干目录项之间建立联系的方法,包括硬链接和软链接两种方式 linux ...

  9. js过滤filter 按条件过滤

    const dataList = this.formData.tableData.filter(item => item.name !== '');

  10. FCC 中级算法题 Everything Be True

    Everything Be True 所有的东西都是真的! 完善编辑器中的every函数,如果集合(collection)中的所有对象都存在对应的属性(pre),并且属性(pre)对应的值为真.函数返 ...