Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
一、前言
刷题啊!!!
开始刷 “剑指 Offer” 31天。刷完时间:2022.3.6 ~ 2022.3.20。
二、题目
题目:
- 斐波那契数列
- 青蛙跳台阶问题
- 股票的最大利润
(1)剑指 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 {
public int fib(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
return fib(n - 1) + fib(n - 2);
}
}
- 思路二:在思路一的基础上,记录下已经计算过的值(避免重复计算)
// 此方法已 AC
// % 1000000007 只是为了防止超出数值
class Solution {
public int fib(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
int [] num = new int[n + 1];
num[0] = 0;
num[1] = 1;
for (int i = 2; i < n + 1; ++i) {
num[i] = (num[i - 1] + num[i - 2]) % 1000000007;
}
return num[n] % 1000000007 ;
}
}
- 思路三:在思路二基础能否再优化?
我们看到,实际只需要 3 个变量就能表示。
AC 代码如下:
class Solution {
public int fib(int n) {
int a = 0, b = 1, sum;
for(int i = 0; i < n; i++){
sum = (a + b) % 1000000007;
a = b;
b = sum;
}
return a;
}
}
(2)剑指 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
题解
斐波那契数列变体应用。
思路和斐波那契数列类似,只不过要注意下 %1000000007
AC 代码如下:
class Solution {
public int numWays(int n) {
int a = 0, b = 1, sum;
for(int i = 0; i <= n; i++){
sum = (a + b) % 1000000007;
a = b;
b = sum;
}
return a;
}
}
(3)剑指 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
题解
既然做
DP,就尽量不要考虑暴力法。
题意:只要找到前天比当前小的对。
- 每日更新最低价格,转移方程:
cost = min(cost, prices[i]) - 每日最大利润,转移方程:
profit = max(profit, prices[i] - min(cost, prices[i]))
AC 代码如下:
class Solution {
public int maxProfit(int[] prices) {
int p = Integer.MAX_VALUE, sum = 0;
for (int price : prices) {
p = Math.min(p, price);
sum = Math.max(sum, price - p);
}
return sum;
}
}