算法专题十九:记忆化搜索(暴搜->记忆化搜索)

什么是记忆化搜索,就是在规律中找出完全一模一样的进行存储,当搜索到这种情况时候,之间从存储的情况中返回

斐波那契数

解法一:递归

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[] memo;
    public int fib(int n) {
        memo=new int[32];
        Arrays.fill(memo,-1);
        return dfs(n);
        
    }

    public int dfs(int n){
        if(memo[n]!=-1){
            return memo[n];
        }
        if(n==0 || n==1){
            return n;
        }
        memo[n]=dfs(n-1)+dfs(n-2);
        return memo[n];
    }
}

解法三:动态规划

java 复制代码
class Solution {
    int[] dp;
    public int fib(int n) {
        dp=new int[31];
        dp[0]=0;
        dp[1]=1;
        for(int i=2;i<=n;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[n];
    }
}

不同路径

62. 不同路径 - 力扣(LeetCode)

直接递归的话,会超出时间的限制

使用记忆化搜索的方式

java 复制代码
class Solution {
    int[][] memo;
    public int uniquePaths(int m, int n) {
        memo=new int[m+1][n+1];
        return dfs(m,n);
        
    }
    public int dfs(int m,int n){
        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;
        }
        memo[m][n]=dfs(m-1,n)+dfs(m,n-1);
        return memo[m][n];
    }
}

使用动态规划

java 复制代码
class Solution {
    int[][] dp;
    public int uniquePaths(int m, int n) {
        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][j-1]+dp[i-1][j];
            }
        }
        return dp[m][n];
    }
}

最长递增子序列

300. 最长递增子序列 - 力扣(LeetCode)

直接使用递归会超时

使用记忆化搜索

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

使用动态规划

java 复制代码
class Solution {
    public int lengthOfLIS(int[] nums) {
        int n=nums.length;
        int[] dp=new int[n];
        int ret=0;
        Arrays.fill(dp,1);
        for(int i=n-1;i>=0;i--){
            for(int j=i+1;j<n;j++){
                if(nums[i]<nums[j]){
                    dp[i]=Math.max(dp[i],dp[j]+1);
                }
            }
            ret=Math.max(ret,dp[i]);
        }
        return ret;
        
    }
}

猜数字的大小Ⅱ

375. 猜数字大小 II - 力扣(LeetCode)

暴搜会超出时间的限制

利用记忆化搜索

取最大值的意思就是 最坏情况(保证所有情况都能猜到10的前提下),然后在所有能猜中10的情况下找出最小值

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){

        int ret=Integer.MAX_VALUE;
        if(left>=right){
            return 0;
        }
        if(memo[left][right]!=0){
            return memo[left][right];
        }
        for(int head=left;head<=right;head++){
            int x=dfs(left,head-1);
            int y=dfs(head+1,right);
            ret=Math.min(Math.max(x,y)+head,ret);
        }
        memo[left][right]=ret;
        return ret;
    }
}

矩阵中的最长递增路径

329. 矩阵中的最长递增路径 - 力扣(LeetCode)

直接暴搜会超时

使用记忆化搜索

java 复制代码
class Solution {
    int[] dx={0,0,-1,1};
    int[] dy={1,-1,0,0};
    int[][] memo;
    int m,n;
    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,memo));
            }
        }
        return ret;
    }

    public int dfs(int[][] ma,int i,int j,int[][] memo){
        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 && ma[x][y]>ma[i][j]){
                ret=Math.max(ret,dfs(ma,x,y,memo)+1);
            }
        }
        memo[i][j]=ret;
        return ret;
    }
}
相关推荐
Charlie_lll3 分钟前
力扣解题-移动零
后端·算法·leetcode
chaser&upper4 分钟前
矩阵革命:在 AtomGit 解码 CANN ops-nn 如何构建 AIGC 的“线性基石”
程序人生·算法
weixin_4997715512 分钟前
C++中的组合模式
开发语言·c++·算法
iAkuya43 分钟前
(leetcode)力扣100 62N皇后问题 (普通回溯(使用set存储),位运算回溯)
算法·leetcode·职场和发展
近津薪荼44 分钟前
dfs专题5——(二叉搜索树中第 K 小的元素)
c++·学习·算法·深度优先
xiaoye-duck1 小时前
吃透 C++ STL list:从基础使用到特性对比,解锁链表容器高效用法
c++·算法·stl
松☆1 小时前
CANN与大模型推理:在边缘端高效运行7B参数语言模型的实践指南
人工智能·算法·语言模型
java干货1 小时前
为什么 “File 10“ 排在 “File 2“ 前面?解决文件名排序的终极算法:自然排序
开发语言·python·算法
皮皮哎哟1 小时前
数据结构:嵌入式常用排序与查找算法精讲
数据结构·算法·排序算法·二分查找·快速排序
程序员清洒1 小时前
CANN模型剪枝:从敏感度感知到硬件稀疏加速的全链路压缩实战
算法·机器学习·剪枝