文章目录
- [一. 力扣 [509. 斐波那契数](https://leetcode.cn/problems/fibonacci-number/description/)](#一. 力扣 509. 斐波那契数)
-
- [1. 题目](#1. 题目)
- [2. 算法原理](#2. 算法原理)
- [3. 代码](#3. 代码)
- [二. 力扣 [62. 不同路径](https://leetcode.cn/problems/unique-paths/)](#二. 力扣 62. 不同路径)
-
- [1. 题目解析](#1. 题目解析)
- [2. 算法原理](#2. 算法原理)
- [3. 代码](#3. 代码)
- [三. 力扣 [375. 猜数字大小 II](https://leetcode.cn/problems/guess-number-higher-or-lower-ii/description/)](#三. 力扣 375. 猜数字大小 II)
-
- [1. 题目解析](#1. 题目解析)
- [2. 算法原理](#2. 算法原理)
- [3. 代码](#3. 代码)
- [四. 力扣 [300. 最长递增子序列](https://leetcode.cn/problems/longest-increasing-subsequence/)](#四. 力扣 300. 最长递增子序列)
-
- [1. 题目解析](#1. 题目解析)
- [2. 算法原理](#2. 算法原理)
- [3. 代码](#3. 代码)
- [五. 力扣 [329. 矩阵中的最长递增路径](https://leetcode.cn/problems/longest-increasing-path-in-a-matrix/description/)](#五. 力扣 329. 矩阵中的最长递增路径)
-
- [1. 题目解析](#1. 题目解析)
- [2. 算法原理](#2. 算法原理)
- [3. 代码](#3. 代码)
一. 力扣 509. 斐波那契数
1. 题目
斐波那契数列相信大家已经很熟悉了, 这里就不过多赘述
2. 算法原理
看下图递归图我们可以发现, 有多次重复值的计算, 这里我们可以用一种容器来将已经计算好的斐波那契数存储起来, 在递归过程中就可以先去容器中看一下, 如果存在, 直接返回即可
3. 代码
java
class Solution {
int[] memory = new int[31];
public int fib(int n) {
for (int i = 0; i < 31; i++) {
memory[i] = -1;
}
return dfs(n);
}
int dfs(int n) {
if (memory[n] != -1) {
return memory[n];
}
if (n == 0 || n == 1) {
memory[n] = n;
return memory[n];
}
memory[n] = dfs(n - 1) + dfs(n - 2);
return memory[n];
}
}
二. 力扣 62. 不同路径
1. 题目解析
题目较简单, 只能走两个方位, 和斐波那契数基本一样
2. 算法原理

3. 代码
java
class Solution {
int[][] memory;
public int uniquePaths(int m, int n) {
memory = new int[m + 1][n + 1];
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
memory[i][j] = -1;
}
}
return dfs(m, n);
}
int dfs(int i, int j) {
if (memory[i][j] != -1) {
return memory[i][j];
}
if (i == 0 || j == 0) {
memory[i][j] = 0;
return 0;
}
if (i == 1 && j == 1) {
memory[i][j] = 1;
return 1;
}
memory[i][j] = dfs(i - 1, j) + dfs(i, j - 1);
return memory[i][j];
}
}
三. 力扣 375. 猜数字大小 II
1. 题目解析
2. 算法原理
3. 代码
java
class Solution {
int[][] memo;
public int getMoneyAmount(int n) {
memo = new int[n + 1][n + 1];
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n; j++) {
memo[i][j] = -1;
}
}
return dfs(1, n);
}
int dfs(int left, int right) {
if (left >= right) {
return 0;
}
if (memo[left][right] != -1) {
return memo[left][right];
}
int min = 0x3f3f3f3f;
// 从left到right选节点
for (int i = left; i <= right; i++) {
int x = dfs(left, i - 1); // 去左子树找值
int y = dfs(i + 1, right);// 去右子树找值
min = Math.min(min, (Math.max(x, y) + i));
}
memo[left][right] = min;
return min;
}
}
四. 力扣 300. 最长递增子序列
1. 题目解析
重点要知道子序列可以不连续
2. 算法原理
3. 代码
java
class Solution {
int[] memo;
int n;
public int lengthOfLIS(int[] nums) {
n = nums.length;
memo = new int[n];
for (int i = 0; i < n; i++) {
memo[i] = -1;
}
// 求多个起点开始的最长长度
int max = 0;
for (int i = 0; i < n; i++) {
max = Math.max(dfs(nums, i), max);
}
return max;
}
int dfs(int[] nums,int pos) {
if (memo[pos] != -1) {
return memo[pos];
}
// 将其设置为1是因为自身也是一个数字,最小为1
int max = 1;
for (int i = pos + 1; i < n; i++) {
if (nums[i] > nums[pos]) {
max = Math.max(dfs(nums, i) + 1, max);
}
}
// 最大值才是pos位置需要的值
memo[pos] = max;
return max;
}
}
五. 力扣 329. 矩阵中的最长递增路径
1. 题目解析
这道题相当于求递增子序列的升级版, 这里可以上下左右四个方位走
2. 算法原理
3. 代码
java
class Solution {
int[][] memo;
int m, n;
int[] dx = {1, -1, 0, 0};
int[] dy = {0, 0, -1, 1};
public int longestIncreasingPath(int[][] matrix) {
m = matrix.length;
n = matrix[0].length;
memo = new int[m][n];
int max = 1;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
max = Math.max(max, dfs(matrix, i, j));
}
}
return max;
}
int dfs(int[][] matrix, int i, int j) {
if (memo[i][j] != 0) {
return memo[i][j];
}
int max = 1;
for (int k = 0; k < 4; k++) {
int x = i + dx[k];
int y = j + dy[k];
if (x >= 0 && x < m && y >= 0 && y < n && matrix[i][j] < matrix[x][y]) {
max = Math.max(max, dfs(matrix, x, y) + 1);
}
}
memo[i][j] = max;
return max;
}
}








