算法奇妙屋(三十三)-DFS的记忆化搜索

文章目录

在文章子序列问题不同路径问题 中, 有题目的动态规划解法

一. 力扣 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;
    }
}
相关推荐
WolfGang0073212 小时前
代码随想录算法训练营 Day13 | 二叉树 part03
数据结构·算法·leetcode
进击的小头2 小时前
第11篇:频率响应绘制方法——伯德图(Bode Plot)
python·算法
2401_883035462 小时前
C++20概念(Concepts)入门指南
开发语言·c++·算法
fengci.2 小时前
PolarD&N困难补充
算法
91刘仁德2 小时前
C++ 内存管理
android·c语言·数据结构·c++·经验分享·笔记·算法
sali-tec2 小时前
C# 基于OpenCv的视觉工作流-章38-BF特征匹配
图像处理·人工智能·opencv·算法·计算机视觉
历程里程碑3 小时前
链表-----
数据结构·线性代数·算法·链表·矩阵·lua·perl
一叶落4383 小时前
167. 两数之和 II - 输入有序数组【C语言题解】
c语言·数据结构·算法·leetcode
地平线开发者3 小时前
征程6 MCU safetylib sample
算法·自动驾驶