算法奇妙屋(三十三)-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;
    }
}
相关推荐
小雨下雨的雨5 分钟前
井字棋AI机器人实现详解 - Minimax算法实战-鸿蒙PC Electron框架完成
前端·人工智能·算法·华为·electron·鸿蒙
xieliyu.3 小时前
Java算法精讲:双指针(三)
java·开发语言·算法
一条小锦吕*3 小时前
基于Spring Boot + 数据可视化 + 协同过滤算法的推荐系统设计与实现(源码+论文+部署全讲解)
spring boot·算法·信息可视化
如竟没有火炬5 小时前
最大矩阵——单调栈
数据结构·python·线性代数·算法·leetcode·矩阵
8Qi85 小时前
LeetCode 1143 & 718:最长公共子序列 / 最长重复子数组
算法·leetcode·职场和发展·动态规划
绿算技术6 小时前
万卡推理集群存储选型分析:从核心架构到应用视角
大数据·科技·算法·架构
想吃火锅10056 小时前
【leetcode】1.两数之和js版
javascript·算法·leetcode
net3m337 小时前
一阶软件低通滤波器算法
人工智能·算法
王老师青少年编程7 小时前
信奥赛C++提高组csp-s之搜索进阶(记忆化搜索案例实践3)
c++·记忆化搜索·方格取数·csp·信奥赛·csp-s·提高组