记忆化搜索题目练习

记忆化搜索

并不是所有递归都可以转化成记忆化搜索,记忆化搜索必须是出现完全重复的递归才可以,仅仅相似不可以转化成记忆化搜索

斐波那契数

题目解析:求第n个斐波那契数


java 复制代码
//递归
class Solution {
    public int fib(int n) {
        return dfs(n);
    }
    public int dfs(int n){
        if(n == 0 || n == 1){
            return n;
        }
        return dfs(n-1) + dfs(n-2);
    }
}
java 复制代码
//记忆化搜索
class Solution {
    int[] memory;
    public int fib(int n) {
        memory = new int[31];
        //初始化这个备忘录
        Arrays.fill(memory,-1);
        return dfs(n);
    }
    public int dfs(int n){
        //已经计算过,备忘录已经存过了,直接返回
        if(memory[n] != -1){
            return memory[n];
        }
        if(n == 0 || n == 1){
            memory[n] = n;//将结果对应放入备忘录中
            return n;
        }
        //返回之前将结果放入备忘录
        memory[n] = dfs(n-1) + dfs(n-2);
        return memory[n];
    }
}
java 复制代码
//动态规划
class Solution {
    int[] dp = new int[31];//记忆化搜索
    public int fib(int n) {
        dp[0] = 0;
        dp[1] = 1;
        for(int i = 2;i <= n;i++){
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[n];
    }
}

不同路径

题目解析 :从start位置到finish位置有多少路径可以走,每次只可以向下或向右走一步
解法一 :
直接递归 ,到第(m,n)位置等于 到第(m-1,n) + 到第(m,n-1),

递归截止 m==0 || n == 0越界了 ,m = 1 && n=1 起始位置

dfs(m,n) = dfs(m-1,n) + dfs(m,n-1),但是时间超时了
解法二:记忆化搜索

这里有重复计算一个位置的问题,可以使用记忆化搜索

intm+1n+1 memo每个位置表示(1,1)到这个位置的路径和
解法三:动态规划

intm+1n+1 dp;先初始化dp11 = 1,直接双重for循环遍历并且给数组对应值即可dpij = dpi-1j + dpij-1


java 复制代码
//记忆化搜索
class Solution {
    public int uniquePaths(int m, int n) {
        int[][] memo = new int[m+1][n+1];
        return dfs(m,n,memo);
    }
    public int dfs(int m,int n,int[][] memo){
        //看是否存过
        if(memo[m][n] != 0){
            return memo[m][n];
        }
        if(m == 0 || n == 0){
            return 0;
        }
        if(m == 1 && n == 1){
            memo[m][n] = 1;
            return 1;
        }
        //更新meno
        memo[m][n] = dfs(m-1,n,memo) + dfs(m,n-1,memo);
        return memo[m][n];
    }
}
java 复制代码
//动态规划
class Solution {
    public int uniquePaths(int m, int n) {
        int[][] dp = new int[m+1][n+1];
        dp[1][1] = 1;
        for(int i = 1;i <= m;i++){
            for(int j = 1;j <= n;j++){
            //起始位置不需要进行初始化了
                if(i == 1 && j == 1){
                    continue;
                }
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        return dp[m][n];
    }
    
}

最长递增自序列

题目解析 :找出一个最长递增自序列,不一定是连续的,但相对顺序是从前向后
解法一:递归

以pos位置开始最长子序列 = 以pos+1位置开始 并且位置值大于 pos位置值开始最长子序列 + 1,但是时间超时
解法二:记忆化搜索

和递归一样,因为这里有重复操作,使用一个memo,下标对应从那个位置开始最长子序列,递归前先看memo中是否有值,返回结果前,更新对应memo值

解法三:动态规划

以pos位置开始最长子序列,依赖从pos+1 ~ n 位置开始最长子序列 ,直接其基础上+1即可,因此可以先从后向前将其最长子序列进行赋值,下标对应的下标就是从那个位置开始最长子序列


java 复制代码
class Solution {
    int n;
    int[] memo;
    public int lengthOfLIS(int[] nums) {
        n = nums.length;
        memo = new int[n];
        int ret = 0;
        for (int i = 0; i < n; i++) {
            ret = Math.max(ret, dfs(nums, i));
        }
        return ret;
    }

    public int dfs(int[] nums, int pos) {
        if(memo[pos] != 0){
            return memo[pos];
        }
        int tem = 1;
        for (int i = pos + 1; i < nums.length; i++) {
            if (nums[i] > nums[pos]) {
                tem = Math.max(tem,dfs(nums,i)+1);
            }
        }
        memo[pos] = tem;
        return memo[pos]; 
    }
}
java 复制代码
class Solution {
    public int lengthOfLIS(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        int ret = 0;
        Arrays.fill(dp,1);//先初始化为1

        //从后向前
        for(int i = n-1;i >= 0;i--){
            for(int j = i+1;j < n;j++){
                //从i+1位置开始后面,选那个数使其dp[i]最大
                if(nums[j] > nums[i]){
                    dp[i] = Math.max(dp[i],dp[j]+1);
                }
            }
            ret = Math.max(ret,dp[i]);
        }
        return ret;
    }
}

猜数字大小||

题目解析: 每次猜错数字都会扣除猜的数字金额,给了一个n,可以选1~n中任意数进行猜测,求出最小金额数可以满足无论猜1到n那个数金额都够
思想 :1,n中任意选一个数分为两部分,找出左部分最小金额点x,找出右边部分最小金额点y,Math.max(x,y)这样两边都满足,找出以所有起点中最小的金额数即可

记忆化搜索:可以使用一个二维数组,下标对应其区间,初始化为0


java 复制代码
//记忆化搜索
class Solution {
    int[][] memo;
    public int getMoneyAmount(int n) {
        memo = new int[n+1][n+1];
        return dfs(1,n);
    }
    public int dfs(int left,int right){
      
        //left == right此时只有一个值可以选,这个就是结果
        //left > right越界了已经
        if(left >= right){
            return 0;
        }
          
        if(memo[left][right] != 0){
            return memo[left][right];
        }

        int ret = Integer.MAX_VALUE;
        for(int head = left ; head <= right;head++){
            int x = dfs(left,head-1);
            int y = dfs(head+1,right);
            //x和y最大值,这样才可以无论选什么左右两边都可以猜出数字
            //但是要从所有结果中选出最小金额可
            ret = Math.min(Math.max(x,y)+head,ret);
        }
        memo[left][right] = ret;
        return memo[left][right];
    }
}

矩阵中的最长递增路径

题目解析 :找出最长递增路径,可以从任意位置作为起点

解法:记忆化搜索

找出以某个位置作为起点的最长路径,需要找其上下左右四个方向那个最长递增路径最长

ret = Math.max(ret,dfs(x,y) + 1)

返回以某个起点是最长路径长度

java 复制代码
class Solution {
    int m,n;
    int[] dx = {1,-1,0,0};
    int[] dy = {0,0,1,-1};
    int[][] memo;
    public int longestIncreasingPath(int[][] matrix) {
        m = matrix.length;
        n = matrix[0].length;
        memo = new int[m][n];
        int ret = 0;
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){

                ret = Math.max(ret,dfs(matrix,i,j));
            }
        }
        return ret;
    }
    public int dfs(int[][] matrix,int i,int j){
        if(memo[i][j] != 0){
            return memo[i][j];
        }
        int ret = 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[x][y] > matrix[i][j]){
                ret = Math.max(ret,dfs(matrix,x,y)+1);
            }
        }
        memo[i][j] = ret;
        return memo[i][j];
    }
}
相关推荐
Sarvartha5 小时前
final 关键字
java·开发语言
2601_952047796 小时前
单一策略深度教程:用轻易云把集成任务的报错实时推送到钉钉机器人
java·机器人·钉钉
yi0116 小时前
LeetCode 219:存在重复元素 II——哈希表记录“最近一次出现的位置”
数据结构·人工智能·笔记·python·算法·leetcode·哈希表
数据狐(Datafox)6 小时前
淘宝图片搜索 API 落地实战:基于以图搜货搭建跨境电商选品系统
java·大数据·微服务
Escalating_xu8 小时前
【C 语言】数据在内存中的存储:补码、大小端、整型陷阱与 IEEE 754 全解析
java·c语言·网络
灯澜忆梦8 小时前
【面向对象编程C++】| 基础语法
java·c++·算法
小蒋观天下9 小时前
专项方案:大场景港口AI安防、多干扰环境下的算法调优与落地实操
人工智能·深度学习·算法·安全·机器学习·计算机视觉·ai大模型
一个风轻云淡9 小时前
GCC 和 GDB命令简单解读
java·linux·前端