算法奇妙屋(三十三)-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;
    }
}
相关推荐
Run_Teenage11 分钟前
算法:线段树
算法
Westward-sun.13 分钟前
YOLOv2算法全方位解析:从BatchNorm到聚类先验框的九大改进
算法·yolo·聚类
扶苏xw15 分钟前
【离散化算法】
算法
码之气三段.16 分钟前
Codeforces Round 1095 (Div. 2) 补题
算法
6Hzlia16 分钟前
【Hot 100 刷题计划】 LeetCode 189. 轮转数组 | C++ 三次反转经典魔法 (O(1) 空间)
c++·算法·leetcode
wuweijianlove18 分钟前
算法可扩展性建模与渐进性能分析的技术7
算法
shehuiyuelaiyuehao43 分钟前
算法14,滑动窗口,找到字符串中所有字母异位词
算法
凯瑟琳.奥古斯特43 分钟前
图论核心考点精讲
开发语言·数据结构·算法·排序算法·哈希算法
WolfGang0073211 小时前
代码随想录算法训练营 Day49 | 图论 part07
算法·图论
啦啦啦_99991 小时前
案例之 逻辑回归_癌症预测
算法·机器学习·逻辑回归