力扣动态规划专题(三)完全背包 518.零钱兑换II 377. 组合总和 Ⅳ 70. 爬楼梯 322. 零钱兑换 279.完全平方数 139.单词拆分 步骤及C++实现

news2024/11/16 5:50:04

文章目录

  • 完全背包
    • 一维dp数组 滚动数组
  • 518.零钱兑换II
  • 377. 组合总和 Ⅳ
  • 70. 爬楼梯
  • 322. 零钱兑换
  • 279.完全平方数
  • 139.单词拆分

完全背包

在这里插入图片描述
完全背包的物品数量是无限的,01背包的物品数量只有一个
完全背包和01背包分许步骤一样,唯一不同就是体现在遍历顺序

有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品都有无限个,也就是一个物品可以放入背包多次,求解将哪些物品装入背包里物品价值总和最大。

背包最大重量为4,问物品有无限个,那么背包能背的物品最大价值是多少?物品为:

重量价值
物品0115
物品1320
物品2430

一维dp数组 滚动数组

  1. 确定dp数组以及下标的含义:一维数组dp[j],容量为j的背包,所背的物品价值可以最大为dp[j]
背包重量j01234
物品0
物品1
物品2
  1. 确定递推公式,有两个方向推出来dp[j]:
  • 不放物品i:由dp[j]本身推出,物品i的重量 > 背包j的重量,物品i无法放进背包中,背包内的价值不变。
  • 放物品i:由dp[j - weight[i]] + value[i]推出,物品i的重量 < 背包j的重量,物品i可以放进背包中,背包内的价值为dp[j - weight[i]] + value[i]
  • 递归公式: dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
  1. dp数组如何初始化
    情况1:j=0时,dp[0]=0,此时背包容量j为0,无论选取什么物品,背包价值总和为0
    情况2:j≠0时,dp[j]会被覆盖更新。
背包重量j01234
物品0015151515
物品10
物品20
  1. 确定遍历顺序
    和01背包最大区别在于遍历顺序
  1. 遍历顺序
  • 01背包的二维dp数组的内外for循环遍历顺序可以互换,先遍历物品或者先遍历背包
  • 01背包的一维dp数组的外层for循环只能先遍历物品,内循环遍历背包。且内循环从大到小遍历,为了保证每个物品仅被添加一次
  • 纯完全背包的一维dp数组内外for循环遍历顺序也可以互换,并且完全背包的物品是可以添加多次的,所以要从小到大去遍历
  • 不是纯完全背包,内外for循环不可以互换,如题518
//01背包
for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
}

//完全背包 先遍历物品,再遍历背包
for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = weight[i]; j <= bagWeight ; j++) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
}

//完全背包 先遍历背包,再遍历物品
for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量
    for(int i = 0; i < weight.size(); i++) { // 遍历物品
        if (j - weight[i] >= 0) dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
    cout << endl;
}
  1. C++实现
void test_CompletePack() {
    vector<int> weight = {1, 3, 4};
    vector<int> value = {15, 20, 30};
    int bagWeight = 4;
    vector<int> dp(bagWeight + 1, 0);
    // 先遍历物品,在遍历背包
    for(int i = 0; i < weight.size(); i++) { // 遍历物品
        for(int j = weight[i]; j <= bagWeight; j++) { // 遍历背包容量
            dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
        }
    }
    /*
    // 先遍历背包,再遍历物品
    for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量
        for(int i = 0; i < weight.size(); i++) { // 遍历物品
            if (j - weight[i] >= 0) dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
        }
    }*/
    cout << dp[bagWeight] << endl;
}
int main() {
    test_CompletePack();
}

518.零钱兑换II

在这里插入图片描述

注意题目说的是组合数,5 = 2 + 2 + 1与5 = 2 + 1 + 2是同一种组合,但是两种排列。

如果求组合数就是外层for循环遍历物品,内层for循环遍历背包。

如果求排列数就是外层for循环遍历背包,内层for循环遍历物品。

步骤

  1. 确定dp数组以及下标的含义
    dp[j]:凑成总金额j的货币组合数为dp[j]

  2. 确定递推公式
    dp[j] 就是所有的 dp[j - coins[i]](考虑coins[i])的情况相加,递推公式:dp[j] += dp[j - coins[i]];
    组合问题推导公式都类似dp[j] += dp[j - nums[i]];

  3. dp数组如何初始化
    j=0时,dp[0]=1,表示只能选coins[i]硬币,且dp[0]=1是递归公式的基础,否则后面推导的值都为0
    j≠0时,dp[j]=0,这样累计加dp[j - coins[i]]的时候才不会影响真正的dp[j]

  4. 确定遍历顺序

  • 外for循环遍历物品(钱币),内层for遍历背包(金钱总额),计算的是组合数,只有{1, 3},不会出现{3, 1}
  • 外for遍历背包(金钱总额),内层for循环遍历物品(钱币),计算的是排列数,会出现{1, 3} 和 {3, 1}两种情况
  • 如果外循环遍历物品coins,内循环遍历背包amount,计算dp[4]的时候,结果集只有 {1,3} 这样的集合,不会有{3,1}这样的集合,因为conis遍历放在外层,3只能出现在1后面
  1. 举例推导dp数组
    输入: amount = 5, coins = [1, 2, 5]

  2. C++实现

class Solution {
public:
    int change(int amount, vector<int>& coins) {
        vector<int> dp(amount+1, 0);
        dp[0] = 1;//初始化
        //组合数 先物品coins 后背包amount
        for(int i=0; i<coins.size(); i++)
        {
            for(int j=coins[i]; j<=amount; j++)
            {
                dp[j] += dp[j-coins[i]];
            }
        }
        return dp[amount];
    }
};

377. 组合总和 Ⅳ

在这里插入图片描述

注意题目说顺序不同的序列被视作不同的组合,求的是排列数,那么外层for遍历背包,内层for循环遍历物品。

如果要把所有排列都列出来,只能使用回溯算法

步骤

  1. 确定dp数组以及下标的含义
    dp[i]:凑成目标正整数为i的排列个数为dp[i]

  2. 确定递推公式
    dp[i](考虑nums[j])可以由 dp[i - nums[j]](不考虑nums[j]) 推导出来,递推公式:dp[j] += dp[j - nums[i]];
    组合问题推导公式都类似dp[j] += dp[j - nums[i]];

  3. dp数组如何初始化
    i=0时,dp[0]=1,没有意义,仅为了避免后面推导的值都为0
    i≠0时,dp[i]=0,这样累计加 dp[i - nums[j]] 的时候才不会影响真正的 dp[i]

  4. 确定遍历顺序

  • 外for循环遍历物品,内层for循环遍历背包,计算的是组合数——518题、494题
  • 外for循环遍历背包,内层for循环遍历物品,计算的是排列数——本题
  1. 举例推导dp数组
    输入: target=4, nums = [1, 2, 3]

  2. C++实现

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        vector<int> dp(target+1, 0);
        dp[0] = 1;
        //排列数 先背包target 后物品nums
        for(int i=0; i<=target; i++)
        {
            for(int j=0; j<nums.size(); j++)
            {
                if(i-nums[j] >= 0 && dp[i] < INT_MAX - dp[i-nums[j]]) dp[i] += dp[i-nums[j]];
            }
        }
        return dp[target];
    }
};

70. 爬楼梯

在这里插入图片描述
注意题目给的示例2中,1阶+2阶 和 2阶+1阶 是不同的组合,求的是排列数,外层for遍历背包,内层for循环遍历物品。

步骤

  1. 确定dp数组以及下标的含义
    dp[i]:爬到有i个台阶的楼顶,有dp[i]种方法

  2. 确定递推公式
    dp[i] 由 dp[i - j] 推导出来,递推公式:dp[i] += dp[i - j];
    组合问题推导公式都类似dp[j] += dp[j - nums[i]];

  3. dp数组如何初始化
    i=0时,dp[0]=1,避免后面推导的值都为0
    i≠0时,dp[i]=0,这样累计加 dp[i - j] 的时候才不会影响真正的 dp[i]

  4. 确定遍历顺序

  • 外for循环遍历物品,内层for循环遍历背包,计算的是组合数——518题、494题
  • 外for循环遍历背包,内层for循环遍历物品,计算的是排列数——本题、377题
  1. 举例推导dp数组
    输入: n=4

  2. C++实现

class Solution {
public:
    int climbStairs(int n) {
        /*
        //01背包 1.只维护两个数值
        if(n <= 1) return n;
        int dp[3];
        dp[1] = 1;
        dp[2] = 2;
        int sum = 0;
        for(int i=3; i<=n; i++)
        {
            sum = dp[1] + dp[2];
            dp[1] = dp[2];
            dp[2] = sum;
        }
        return dp[2];

        //01背包 2.维护整个数组
        if(n <= 1) return n;
        vector<int> dp(n+1);
        dp[1] = 1;
        dp[2] = 2;
        for(int i=3; i<=n; i++)
        {
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[n];*/

        //完全背包
        vector<int> dp(n+1, 0);
        dp[0] = 1;
        //排列数 先背包 后物品 
        //内层for循环的2表示一次最多可以爬2层台阶
        for (int i = 1; i <= n; i++) { // 遍历背包
            for (int j = 1; j <= 2; j++) { // 遍历物品
                if (i - j >= 0) dp[i] += dp[i - j];
            }
        }
        return dp[n];
    }
};

如果题目改为:一步一个台阶,两个台阶,三个台阶,…,直到 m个台阶。问有多少种不同的方法可以爬到楼顶?

  • 1阶,2阶,… m阶就是物品,楼顶就是背包。每一阶可以重复使用,跳了1阶,还可以继续跳1阶
  • 问跳到楼顶有几种方法其实就是问装满背包有几种方法——完全背包
  • C++实现时,可以把完全背包方法中的 内层for循环中的2改成对应的m

322. 零钱兑换

在这里插入图片描述
注意题目说每种硬币的数量是无限的,完全背包

步骤

  1. 确定dp数组以及下标的含义
    dp[j]:凑足总额为j所需钱币的最少个数为dp[j]

  2. 确定递推公式
    dp[j](考虑coins[i]),由dp[j - coins[i]]推导而来,再加上一个钱币coins[i],就是dp[j]
    同时,dp[j] 取所有 dp[j - coins[i]] + 1 中最小的,递推公式:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);

  3. dp数组如何初始化
    j=0时,dp[0]=0,凑足总金额为0所需钱币的个数一定是0
    j≠0时,dp[j]=INT_MAX,dp[j]必须初始化为一个最大的数,否则在 min(dp[j - coins[i]] + 1, dp[j])比较中会被初始值覆盖

  4. 确定遍历顺序

  • 外for循环遍历物品,内层for循环遍历背包,计算的是组合数——518题、494题
  • 外for循环遍历背包,内层for循环遍历物品,计算的是排列数——377题、70题
  • 本题并不强调是组合数还是排列数,只需要钱币个数最小,是纯完全背包问题。因此先遍历物品或者先遍历背包,并且内循环正序遍历
  1. 举例推导dp数组
    输入: coins = [1, 2, 5], amount = 5

  2. C++实现

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> dp(amount+1, INT_MAX);
        dp[0] = 0;
        //先物品 后背包
        for(int i=0; i<coins.size(); i++)
        {
            for(int j=coins[i]; j<=amount; j++)
            {
                if(dp[j - coins[i]] != INT_MAX) dp[j] = min(dp[j], dp[j-coins[i]]+1);
            }
        }
        //先背包 后物品
        /*for(int i=0; i<=amount;i++)
        {
            for(int j=0; j<coins.size(); j++)
            {
                if(i - coins[j] >= 0 && dp[i - coins[j]] != INT_MAX) dp[i] = min(dp[i], dp[i-coins[j]]+1);
            }
        }*/
        if (dp[amount] == INT_MAX) return -1;
        return dp[amount];
    }
};

279.完全平方数

在这里插入图片描述
完全平方数就是物品(可以无限件使用),凑个正整数n就是背包,问凑满这个背包最少有多少物品,完全背包问题

步骤

  1. 确定dp数组以及下标的含义
    dp[j]:和为j的完全平方数的最少数量为dp[j]

  2. 确定递推公式
    dp[j],由 dp[j - i * i] 推导而来,再加上1就是dp[j]

同时,dp[j] 取所有 dp[j - i * i] + 1 中最小的,递推公式:dp[j] = min(dp[j - i * i] + 1, dp[j]);

  1. dp数组如何初始化
    j=0时,dp[0]=0
    j≠0时,dp[j]=INT_MAX,dp[j]必须初始化为一个最大的数,否则在 min(dp[j - coins[i]] + 1, dp[j])比较中会被初始值覆盖

  2. 确定遍历顺序

  • 外for循环遍历物品,内层for循环遍历背包,计算的是组合数——518题、494题
  • 外for循环遍历背包,内层for循环遍历物品,计算的是排列数——377题、70题
  • 题目并不强调是组合数还是排列数,纯完全背包问题。因此先遍历物品或者先遍历背包,并且内循环正序遍历——本题、322题
  1. 举例推导dp数组
    输入: n = 5

  2. C++实现

class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n+1, INT_MAX);
        dp[0] = 0;
        //先背包 后物品
        for(int i=0; i<=n; i++)
        {
            for(int j=1; j*j<=i; j++)
            {
                dp[i] = min(dp[i], dp[i-j*j]+1);
            }
        }
        
        //先物品 后背包
        /*for(int i=1; i*i<=n; i++)
        {
            for(int j=i*i; j<=n ;j++)
            {
                dp[j] = min(dp[j], dp[j-i*i]+1);
            }
        }*/
        return dp[n];
    }
};

139.单词拆分

在这里插入图片描述
在这里插入图片描述
物品:单词wordDict;背包:字符串s;单词能否组成字符串s:物品能否把背包装满;题目中可以重复使用字典中的单词,完全背包问题

步骤

  1. 确定dp数组以及下标的含义
    dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。

  2. 确定递推公式
    如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,dp[i]是true,j < i
    递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) dp[i] = true

  3. dp数组如何初始化
    i=0时,dp[0]=true
    i≠0时,dp[i]=false,只要没有被覆盖说明都是不可拆分为一个或多个在字典中出现的单词。

  4. 确定遍历顺序
    组成字符串之间有顺序,求的是排列数,先遍历背包,再遍历物品。例如,“apple”, “pen” 是物品,“applepenapple"只能由 “apple” + “pen” + “apple” ,不能是"apple” + “apple” + “pen” 或者 “pen” + “apple” + “apple” ,强调物品顺序。

  • 外for循环遍历物品,内层for循环遍历背包,计算的是组合数——518题、494题
  • 外for循环遍历背包,内层for循环遍历物品,计算的是排列数——377题、70题、本题
  • 纯完全背包问题,先遍历物品或者先遍历背包,内循环正序遍历,计算的是最小数——322题、279题
  1. 举例推导dp数组
    输入: s = “leetcode”, wordDict = [“leet”, “code”]为例

  2. C++实现

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> wordset(wordDict.begin(), wordDict.end());//为了使用find查找函数
        vector<bool> dp(s.size()+1, false);
        dp[0] = true;
        //排列数 先背包 后物品
        for(int i=1;i<=s.size(); i++)
        {
            for(int j=0; j<i; j++)
            {
                string word = s.substr(j, i-j);//substr(起始位置,截取的个数)
                if(wordset.find(word) != wordset.end() && dp[j]) dp[i] = true;
            }
        }       
        return dp[s.size()];
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JVM内存分析:Aviator低版本内存泄漏问题分析

目录 1.频繁FullGC告警 2.堆转储操作生成dump文件 3.利用MAT工具分析dump文件 3.1 大对象视图分析内存泄漏原因 3.2 Aviator框架中什么地方用到ThreadLocal&#xff1f; 3.3 fnLocal为什么存在内存泄漏&#xff1f; 3.4 LambdaFunctionBootstrap为什么没有释放&#xff…

002mavenSettings配置

Maven –Settings 官网说明https://maven.apache.org/guides/mini/guide-mirror-settings.html 官网说明 模板 <?xml version"1.0" encoding"UTF-8"?> <settings xmlns"http://maven.apache.org/SETTINGS/1.0.0"xmlns:xsi"htt…

【Redis】持久化机制

一、三种持久化机制 RDF快照&#xff1a;通过某一时刻的快照&#xff0c;将数据以二进制形式永久存储在磁盘中。AOF&#xff1a;将每个修改命令通过write函数追加到文件中。混合持久化&#xff1a;AOF重写时&#xff0c;将重写这一刻之前的内存做RDB快照存储&#xff0c;并将此…

前端vue上拉加载下拉刷新组件,支持列表分页 本地分页

前端vue上拉加载下拉刷新组件,支持列表分页 本地分页, 下载完整代码请访问uni-app插件市场地址: https://ext.dcloud.net.cn/plugin?id12942 喜欢我的前端组件分享文章的&#xff0c;帮忙加个关注&#xff0c;非常感谢&#x1f64f;&#x1f64f; 效果图如下: #### 使用方法…

StarRocks 文章收集

StarRocks在58的实践 StarRocks在58的实践 - 墨天轮StarRocks在58的实践 --2022-06-08https://www.modb.pro/db/639611 StarRocks之系统架构 StarRocks之系统架构 - 墨天轮https://www.modb.pro/db/610300 StarRocks小规模集群部署最佳实践(1/2) 0016.S StarRocks小规模集…

JDBC 2023年最新学习笔记!

课程笔记说明 我的笔记是来源于尚硅谷的赵伟风老师的2023年最新版jdbc的课程 视频链接&#xff1a; 尚硅谷JDBC实战教程&#xff08;2023最新版jdbc&#xff0c;JDK17MySQL8&#xff09;_哔哩哔哩_bilibili 课程资料&#xff1a; 关注“尚硅谷教育”&#xff0c;后台回复J…

中年“难”人

对于每个打工人而言&#xff0c;人生无外乎两种状态&#xff0c;要么已是中年人&#xff0c;要么走在成为中年人的路上&#xff0c;可是当下横空出世的中产作死三件套&#xff0c;让每个打工人都不寒而栗 - 房贷近千万&#xff1b; 配偶不上班&#xff1b; 两娃上国际。 这个…

走在时代前沿:宝洁的柔性供应链战略及其对全球快消品市场的影响

01 先进的供应链计划不断推动宝洁引领全球快速消费品市场 宝洁公司&#xff08;Procter & Gamble&#xff09;成立于1837年&#xff0c;是全球知名的消费品公司&#xff0c;公司拥有多个知名品牌&#xff0c;如宝洁、海飞丝、汰渍、奥妙、潘婷、威露士等&#xff0c;这些产…

程序员必须掌握的消息中间件-RabbitMQ

一、Rabbit 概述 RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用来通过普通协议在完全不同的应用中间共享数据&#xff0c;RabbitMQ 是使用 Erlang 语言来编写的&#xff0c;并且 RabbitMQ 是基于 AMQP 协议的。 特点&#xff1a; 开源、性能优秀 Erlang 语言最初用…

【ChatGPT+XMind超级详细的保姆级思维导图教程】

&#x1f680; AI &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;CSDN…

Spring Boot 异常报告器解析

基于Spring Boot 3.1.0 系列文章 Spring Boot 源码阅读初始化环境搭建Spring Boot 框架整体启动流程详解Spring Boot 系统初始化器详解Spring Boot 监听器详解Spring Boot banner详解Spring Boot 属性配置解析Spring Boot 属性加载原理解析Spring Boot 异常报告器解析 创建自定…

怎么查投票人画展投票链接怎么做微信链接投票

近些年来&#xff0c;第三方的微信投票制作平台如雨后春笋般络绎不绝。随着手机的互联网的发展及微信开放平台各项基于手机能力的开放&#xff0c;更多人选择微信投票小程序平台&#xff0c;因为它有非常大的优势。 1.它比起微信公众号自带的投票系统、传统的H5投票系统有可以图…

C语言入门万字笔记

C语言一经出现就以其功能丰富、表达能力强、灵活方便、应用面广等特点迅速在全世界普及和推广。C语言不但执行效率高而且可移植性好&#xff0c;可以用来开发应用软件、驱动、操作系统等。C语言也是其它众多高级语言的鼻祖语言&#xff0c;所以说学习C语言是进入编程世界的必修…

机器学习、计算机视觉和深度学习

机器学习、计算机视觉和深度学习 1 什么是机器学习&#xff1f;2 机器学习的类型3 什么是计算机视觉&#xff1f;4 计算机视觉的机器学习应用5 总结参考 这篇博客将简要介绍&#xff1a;机器学习和用于计算机视觉的机器学习。 想象一下&#xff1a;你可以使用人脸检测算法在图…

【后端】SSM框架下REST风格代码注释详解

前言 最近学习了一下SSM&#xff0c;不得不说&#xff0c;spring不用注解真的是天打雷劈&#xff0c;就那个bean真的就是折磨人。 下面是我总结的spring注解。 Value 此注解可以用来获取导入的jdbc.properties文件的值。 Value("${jdbc.driver}")private String…

【C++】C++11新特性重点:可变参数+lambda

C11新特性第二篇重点 文章目录 上一篇的补充一、可变参数模板二、lambda函数总结 前言 上一篇我们重点讲解了右值引用移动语义&#xff0c;关于移动构造和移动赋值还有一些需要补充的知识&#xff1a; 如果你没有自己实现移动构造函数&#xff0c;且没有实现析构函数 、拷贝构…

dubbo 3.2.0 的filterChain 简要分析

dubbo 3.2.0 的filterChain 的核心类是DefaultFilterChainBuilder 。 Builder public class DefaultFilterChainBuilder implements FilterChainBuilder {的buildInvokerChain函数 对于consumer refer Overridepublic <T> Invoker<T> buildInvokerChain(final I…

Java自动化测试(web自动化测试框架 )

测试数据 测试地址 http://120.78.128.25:8765/ 投资人 13323234545 lemon123456 借款人 13323234444 lemonbest 后台地址 http://120.78.128.25:8765/Admin/Index/login.html lemon7 lemonbest Page Object PO简介 https://www.selenium.dev/documentation/en/g…

如何把在线K歌“玩起来”——专访撕歌音视频架构师程乐

编者按&#xff1a;在线K歌的业务已经发展了十年&#xff0c;程乐在音视频领域也闯荡了十年&#xff0c;甚至更久。为什么选择在线K歌领域&#xff1f;如何走过“漫长的季节”&#xff0c;迎来新的风景&#xff1f;如何在“在线K歌”这块难啃的骨头里分点肉&#xff1f;在这一连…

【存储】cache memory、primary memory and secondary memory

一、提要二、计算机的存储结构三、高速缓存&#xff1a;cache memory四、主存&#xff1a;Primary memory4.1 RAM4.11 SRAM 和 DRAM的概念4.12 SRAM 和 DRAM的应用场景 4.2 ROM4.21 PROM4.22 EPROM▶ EEPROM▶ UVEPROM 五、辅助存储器&#xff1a;secondary memory六、单片机的…