【递归、搜索与回溯】记忆化搜索

一、经验总结

以斐波那契数为例引入今天的主角:记忆化搜索和动态规划

题目链接

509. 斐波那契数 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

//解法二:递归->记忆化搜索
class Solution {
    int mem[31]; //备忘录
public:
    Solution()
    {
        memset(mem, -1, sizeof(mem));
    }
    int fib(int n) {
        if(mem[n] != -1) return mem[n];
        if(n==0 || n==1) 
            mem[n] = n;     
        else
            mem[n] = fib(n-1) + fib(n-2);
        return mem[n];
    }
};

//解法三:动态规划
class Solution {
    int dp[31]; //dp[i]表示第i个斐波那契数
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]; //返回值
    }
};

二、相关编程题

2.1 不同路径

题目链接

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

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

动态规划:从(1, 1)位置走起,到(m, n)位置结束。将第0行,第0列空下初始化为0方便处理边界情况。

编写代码

//解法一:记忆化搜索——自顶向下
class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> memo(m+1, vector<int>(n+1, 0));
        return dfs(m, n, memo);
    }

    int dfs(int m, int n, vector<vector<int>>& memo)
    {
        if(m<1 || n<1) return 0;
        if(m==1 && n==1) return 1;
        if(memo[m][n]!=0) return memo[m][n];
        memo[m][n] = dfs(m-1, n, memo)+dfs(m, n-1, memo);
        return memo[m][n];
    }
};

//解法二:动态规划——自底向上
class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m+1, vector<int>(n+1, 0));
        dp[1][1] = 1;
        for(int i = 1; i <= m; ++i)
        {
            for(int j = 1; j <= n; ++j)
            {
                if(i==1 && j==1) continue;
                else dp[i][j] = dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[m][n];
    }
};

2.2 最长递增子序列

题目链接

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

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

//解法一:记忆化搜索——自顶向下
class Solution {
    int n;
public:
    int lengthOfLIS(vector<int>& nums) {
        n = nums.size();
        vector<int> memo(n, 0); //记录的是每个位置对应的最长递增子序列
        int ret = 1;
        for(int i = 0; i < n; ++i) //选择子序列的首元素
        {
            ret = max(ret, DFS(nums, i, memo));
        }
        return ret;
    }

    int DFS(vector<int>& nums, int pos, vector<int>& memo)
    {
        if(memo[pos] != 0) return memo[pos];
        int ret = 1; //这里一定要初始化为1,最后一个元素不进入循环直接返回1
        for(int i = pos+1; i < n; ++i)
        {
            if(nums[i] > nums[pos]) //要满足递增的要求
            {
                ret = max(ret, DFS(nums, i, memo)+1);
            }
        }
        memo[pos] = ret;
        return ret;
    }
};

//解法二:动态规划——自底向上
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        vector<int> dp(n, 1);
        dp[n-1] = 1; //初始化:最后一个位置的长度为1
        int ret = 1;
        for(int i = n-1; i >= 0; --i) //填表顺序:从右向左
        {
            for(int j = i+1; j < n; ++j) //状态转移方程
            {
                if(nums[j] > nums[i])
                    dp[i] = max(dp[i], dp[j]+1);
            }
            ret = max(ret, dp[i]);
        }
        return ret;
    }
};

2.3 猜数字大小Ⅱ

题目链接

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

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
public:
    int getMoneyAmount(int n) {
        vector<vector<int>> memo(n+1, vector<int>(n+1, 0)); //memo记录的是i位置的最小现金
        return DFS(1, n, memo); //DFS返回的是确保获胜的最小现金数
    }

    int DFS(int l, int r, vector<vector<int>>& memo)
    {
        if(l >= r) return 0; //l>r区间不存在;l==r区间内只有一个元素,一次选中不需要付钱
        if(memo[l][r] != 0) return memo[l][r];
        int ret = INT_MAX;
        for(int i = l; i <= r; ++i)
        {
            int left = DFS(l, i-1, memo); //左区间
            int right = DFS(i+1, r, memo); //右区间
            int tmp = max(left, right)+i; //确保获胜取max
            ret = min(ret, tmp); //最小现金数取min
        }
        memo[l][r] = ret;
        return ret;
    }
};

2.4 矩阵中的最长递增路径

题目链接

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

题目描述

在这里插入图片描述

算法原理

见代码

编写代码

class Solution {
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    int m, n;
public:
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        m = matrix.size(), n = matrix[0].size();
        vector<vector<int>> memo(m, vector<int>(n, 0));
        int ret = 0;
        // 选择路径起点
        for(int i = 0; i < m; ++i)
        {
            for(int j = 0; j < n; ++j)
            {
                ret = max(DFS(matrix, i, j, memo), ret); //DFS暴搜+memo优化
            }
        }
        return ret;
    }

    int DFS(vector<vector<int>>& matrix, int r, int c, vector<vector<int>>& memo)
    {
        if(memo[r][c] != 0) return memo[r][c];
        int ret = 1;
        for(int i = 0; i < 4; ++i)
        {
            int x = r+dx[i], y = c+dy[i];
            if(x>=0 && x<m && y>=0 && y<n && matrix[x][y]>matrix[r][c])
            {
                ret = max(DFS(matrix, x, y, memo)+1, ret);
            }
        }
        memo[r][c] = ret;
        return ret;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/716222.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

揭秘未来:用线性回归模型预测一切的秘密武器!

线性回归模型 1. 引言2. 理论基础2.1 线性回归模型的定义与原理原理与关键假设模型参数估计 2.2 模型评估指标2.2.1 残差分析2.2.2 拟合优度指标2.2.3 统计检验 3. 应用场景3.1. 金融领域中的应用3.2. 医疗健康领域中的应用3.3. 其他领域的应用 4. 实例分析4.1、数据集选择4.2、…

目标检测算法YOLOv10简介

YOLOv10由Ao Wang等人于2024年提出&#xff0c;论文名为&#xff1a;《YOLOv10: Real-Time End-to-End Object Detection》&#xff0c;论文见&#xff1a;https://arxiv.org/pdf/2405.14458 &#xff1b;源码见: https://github.com/THU-MIG/yolov10 以下内容主要来自论文&a…

Open To Buy(OTB)计划:零售业者的库存管理利器

在当今快速变化的服装市场中&#xff0c;如何高效、精准地进行商品管理成为了服装企业竞争的关键。OTB&#xff08;Open-to-Buy&#xff09;作为一种有效的商品管理方法&#xff0c;在企业管理中扮演着至关重要的角色。它基于预算、商品计划以及市场需求等多维度因素&#xff0…

《优化接口设计的思路》系列:第1篇—什么是接口缓存

一、缓存的定义&#xff1a; 缓存是一种存储数据的技术&#xff0c;用于提高数据访问的速度和效率。缓存通常存储在内存中&#xff0c;因为内存访问速度远快于磁盘和网络。数据接口通常会使用缓存技术&#xff0c;以降低对后端数据存储和处理的压力&#xff0c;提高系统性能。…

CSAPP -lecture01

##01COURSE OVERVIEW int or not intergers ,float and not reals that you need to understand what the system dose ,what make it run wll,what make it run poorly .in order to be able to do that kind of optimization

期货到底难在哪里?

第一难&#xff1a;使用杠杠&#xff0c;杠杠放大的其实是你性格、天赋和技能上的弱点&#xff0c;同时相应缩小你这三个方面的优点&#xff1b;第二难&#xff1a;双向交易。如果只能做多&#xff0c;理论上你每次交易将有50%的概率盈利。现在既能做多又能做空&#xff0c;只剩…

Semantic Kernel 直接调用本地大模型与阿里云灵积 DashScope

本文主要介绍如何在无需网关&#xff0c;无需配置 HttpClient 的情况下&#xff0c;使用 Semantic Kernel 直接调用本地大模型与阿里云灵积 DashScope 等 OpenAI 接口兼容的大模型服务。 1. 背景 一直以来&#xff0c;我们都在探索如何更好地利用大型语言模型&#xff08;LLM&…

如何快速搭建产业数字化生态链?

如何快速搭建产业数字化生态链&#xff1f;这是当下许多企业都在思索的关键问题。 首先&#xff0c;要明确自身的核之心优势与定位&#xff0c;找到在数字化生态中的独特价值。 加强与产业链上下游企业的合作与协同&#xff0c;打破信息壁垒&#xff0c;实现资源共享与互补。 注…

重生奇迹mu圣导师介绍

出生地&#xff1a;勇者大陆 性 别&#xff1a;男 擅 长&#xff1a;统率&宠物使用 转 职&#xff1a;祭师&#xff08;3转&#xff09; 介 绍&#xff1a;当玩家账号中有一个Lv250以上角色时&#xff0c;便可以创建职业为圣导师的新角色&#xff0c;圣导师每升一级获得…

最适合程序员的编程字体,漂亮、独特、优雅!(2024-06-17)

Monaco Monaco 字体是一款专为编程和代码编辑设计的等宽字体&#xff0c;以其简洁明了的无衬线设计风格、高可读性和清晰的字符区分度&#xff0c;受到开发者们的青睐&#xff0c;Mac 自带 Monaco 字体。 Consolas Consolas 是一款等宽无衬线字体&#xff0c;专为编程和代码编…

C#语言入门详解 --- 方法(含传值 输出 引用 数组)

方法 方法标准式 <Access Specifier> <Return Type> <Method Name>(Parameter List) { Method Body } 让我们逐一对每一个模块进行解释&#xff1a; Access Specifier&#xff1a;访问修饰符&#xff0c;这决定了接下来的主题的可见性&#xff0c;包含p…

基于LangChain-Chatchat实现的RAG-本地知识库的问答应用[3]-参数配置详细版

基于LangChain-Chatchat实现的RAG-本地知识库的问答应用[3]-参数配置详细版 在开始参数配置之前,先执行以下脚本 python copy_config_example.py该脚本将会将所有config目录下的配置文件样例复制一份到config目录下,方便开发者进行配置。 接着,开发者可以根据自己的需求,对…

20个超实用的VS Code扩展(2024年版)

大家好&#xff0c;今天小程给大家带来一篇关于 VS Code 扩展的文章。VS Code 这几年做得是风生水起&#xff0c;可以算得上是微软的良心产品&#xff0c;其最大的优势就是拥有众多高质量的扩展。在本文中&#xff0c;将向大家推荐一些我认为在 2024 年对开发者来说又实用又好用…

GPT_AI高速发展中什么是Prompt提示词?

提示词&#xff08;Prompt&#xff09;是给大语言模型&#xff08;以下简称模型&#xff09;的输入文本&#xff0c;用于指定模型应该执行什么样的任务并生成什么样的输出。 提示词发挥了“提示” 模型 应该做什么的作用。设计高质量的提示词需要根据目标任务和模型能力进行精…

动态 ETL 管道:使用非结构化 IO 将 AI 与 MinIO 和 Weaviate 的 Web

在现代数据驱动的环境中&#xff0c;网络是一个无穷无尽的信息来源&#xff0c;为洞察力和创新提供了巨大的潜力。然而&#xff0c;挑战在于提取、构建和分析这片浩瀚的数据海洋&#xff0c;使其具有可操作性。这就是Unstructured-IO 的创新&#xff0c;结合MinIO的对象存储和W…

hadoop搭建本地hive库保姆级教程

安装本地hive 安装的前提是hadoop完全分布式可以正常的跑起来 第一部分&#xff1a;安装mysql8.0 1.安装wget工具 yum -y install wget2.通过wget工具下载mysql源文件 注意&#xff1a;以下版本过高&#xff0c;后面安装MySQL源会失败&#xff0c;所以建议刚开始尝试换成…

Python 五子棋游戏(人人对战人机对战)【含Python源码 MX_006期】

系统简介&#xff1a; 五子棋是一种双人对弈的策略棋类游戏&#xff0c;玩家轮流在棋盘上落子&#xff0c;目标是通过在水平、垂直或对角线上连成一条直线的方式&#xff0c;最先在棋盘上形成连续的五颗棋子。五子棋的规则相对简单&#xff0c;但是需要玩家在落子过程中进行深思…

python14 字典类型

字典类型 键值对方式&#xff0c;可变数据类型&#xff0c;所以有增删改功能 声明方式1 {} 大括号&#xff0c;示例 d {key1 : value1, key2 : value2, key3 : value3 ....} 声明方式2 使用内置函数 dict() 创建1)通过映射函数创建字典zip(list1,list2) 继承了序列的所有操作 …

数字人源码部署怎么做?如何高效搭建好用的数字人系统?

作为人工智能时代的风口项目&#xff0c;AI数字人自出现之日起便引发了大量的关注。不少创业者都有了搭建数字人系统的想法&#xff0c;但却苦于没有强大的专业背景和雄厚资金支撑&#xff0c;只能在局外徘徊&#xff0c;而这恰恰为数字人源码公司推出的数字人源码部署服务的火…

第28讲:Ceph集群使用RBD块存储与K8S Volumes集成

文章目录 1.Ceph集群使用RBD块存储与K8S集成简介2.Ceph集群RBD块存储与K8S Volume集成2.1.在Ceph集群中创建K8S集群使用的块存储2.2.创建用于K8S访问Ceph RBD块设备的认证用户2.3.将认证用户的Key存储在K8S Secret资源中2.4.在K8S集群的所有节点中安装Ceph命令2.5.创建Pod资源使…