【算法学习】——整数划分问题详解(动态规划)

🧮整数划分问题是一个较为常见的算法题,很多问题从整数划分这里出发,进行包装,形成新的题目,所以完全理解整数划分的解决思路对于之后的进一步学习算法是很有帮助的。

「整数划分」通常使用「动态规划」解决,本篇将如何使用动态规划分析和解决这个问题。

可以的话,点赞👍和收藏💌支持一下哦!

文章目录

    • 1. 问题描述📝
    • 2. 动态规划简述💡
      • 动态规划算法的基本要素
      • 2.1动态规划基本思想
      • 2.2 解题步骤
    • 3. 问题分析🔍
      • 3.1 明确问题的最优值和最优解
      • 3.2 求递归定义最优值的公式
        • 分析不同规模子问题之间的关系
        • 根据分析结果写动态规划求解的递推公式
      • 4. 以自底向上方式计算最优值💻
    • 5. 优化 📊
      • 问题回顾
      • 原始二维动态规划
      • 优化为一维动态规划
        • 优化后的递推公式
        • 递推公式的推导
      • 实现优化后的程序
      • 优化总结
    • 6. 扩展思考 🎯
      • 6.1 相关问题
      • 6.2 实际应用场景
    • 7. 练习建议 📝
    • 总结 🎉
      • 🤔 思考题

1. 问题描述📝

将正整数n表示成一系列正整数之和: n = n 1 + n 2 + … + n k n=n_1+n_2+…+n_k n=n1+n2++nk,其中 n 1 ≥ n 2 ≥ … ≥ n k ≥ 1 , k ≥ 1 n_1 \geq n_2≥…≥n_k≥1,k≥1 n1n2nk1k1
正整数n的这种表示称为正整数n的划分,求正整数n的不同划分个数。

示例
正整数6有如下11种不同的划分:

6;
5+1;
4+2,4+1+1;
3+3,3+2+1,3+1+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1。


2. 动态规划简述💡

在使用动态规划解题之前,先简要回顾一下。

动态规划算法适用于求解最优化问题

如何判断这个问题能使用「动态规划」解决呢? 主要看是否具有两个要素

动态规划算法的基本要素

  1. 最优子结构性质

问题的最优解包含着其子问题的最优解。这种性质称为最优子结构性质

  1. 子问题重叠性质

递归算法求解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。这种性质称为子问题的重叠性质

2.1动态规划基本思想

动态规划算法与分治法类似,其基本思想是:
将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
动态规划算法与分治法不同的是,经分解得到的子问题往往不是相互独立的,有大量子问题会重复出现。
为了避免重复计算,动态规划法是用一个来存放一计算过的子问题。

2.2 解题步骤

通常按四步骤设计动态规划算法:
(1)找出最优解的性质,并刻画其结构特征;
(2)递归定义求最优值的公式; ——(最为关键)
(3)以自底向上方式计算最优值;
(4)根据计算最优值时得到的信息,构造最优解。(看题目要求,有的题目不要求构造最优解)


接下来根据动态规划的思想,进行问题分析。

3. 问题分析🔍

3.1 明确问题的最优值和最优解

根据题意可知,最优值就是不同划分的个数

3.2 求递归定义最优值的公式

分析不同规模子问题之间的关系

在正整数n的所有不同划分中,将最大加数不大于m的划分个数记作q(n,m),可以建立q(n,m)的如下递归关系

  1. q ( n , 1 ) = 1 , n ≥ 1 ; q(n,1)=1,n \geq 1; q(n,1)=1,n1;

    当最大加数m不大于1时,任何正整数n只有一种划分形式,即 n = 1 + 1 + . . . + 1 ⏞ n n=\overset{n} {\overbrace{1+1+...+1}} n=1+1+...+1 n

  2. q ( n , m ) = q ( n , n ) , m ≥ n ; q(n,m)=q(n,n),m \geq n; q(n,m)=q(n,n),mn;

    最大加数实际上不能大于n

  3. q ( n , n ) = 1 + q ( n , n − 1 ) ; q(n,n)=1+q(n,n-1); q(n,n)=1+q(n,n1);

    正整数n的最大加数不大于n的划分由最大加数=n的划分和最大加数≤n-1的划分组成。

  4. q ( n , m ) = q ( n , m − 1 ) + q ( n − m , m ) , n > m > 1 ; q(n,m)=q(n,m-1)+q(n-m,m),n>m>1; q(n,m)=q(n,m1)+q(nm,m),n>m>1;

    正整数n的最大加数不大于m的划分由最大加数≤m-1的划分和最大加数=m的划分组成。

理解一下:

  • 最大加数=m的划分: 相当于给定了一个前提条件,即至少有一个划分成m,故先减去这个被划分走了的m,则剩下的可以再划分的大小为 “n-m”,故最终的表达式为q(n-m,m)
  • 最大加数≤m-1的划分: 上一步已经求出了最大划分为m的情况的划分数,所以接下来就只需求出 最大划分为m-1 这一情况的划分数,那么我们只需要约束最大划分数为m-1,进而得到最终的表达式为q(n,m-1)

注:
在理解了递归关系4之后,我们再反过来分析关系3:
3.其实是4.的特殊情况,即m=n,那么
q ( n , n ) = q ( n , n − 1 ) + q ( n − n , n ) − − 式① q(n,n) = q(n, n-1) + q(n-n, n) -- 式① q(n,n)=q(n,n1)+q(nn,n)
= q ( n , n − 1 ) + q ( 0 , n ) − − 式② = q(n, n-1) + q(0, n) -- 式② =q(n,n1)+q(0,n)

  • 在这里我们单单从表达式上理解的话,q(0, n) 在题目中是没有意义的,因为这是一个 “正整数” 的划分问题,n=0相当于没有东西可以划分了。
  • 但是从实际意义上出发进行理解,q(n-n,n)就是最大加数=n的划分,即n大的正整数需要划分成包含一个大小为n的划分组合,那不就是只有“ n=n ”这一个划分嘛。

综上,我们可以知道:q(n-n, n) = 1,从而得到前面的关系3:q(n, n-1) + q(n-n, n) = q(n, n-1) + 1,而写成式②这样反而会导致表达式失去意义。

递推公式的直观理解 🤔
让我们通过一个例子来理解:
假设n=5,m=3时:
q(5,3)可以分为两类:
不使用 3 作为加数:q(5,2)
使用至少一个 3:q(5-3,3) = q(2,2)

最终的递推公式:
q ( n , m ) = { 1 ,  n ≥ 1 , m = 1 q ( n , n ) ,  n < m 1 + q ( n , n − 1 ) ,  n = m q ( n , m − 1 ) + q ( n − m , m ) ,  n > m > 1 q(n,m)=\begin{cases} 1 & \text{, } n \geq 1,m=1 \\q(n,n) & \text{, } n < m & \\1 + q(n,n-1) & \text{, } n = m \\q(n,m-1)+q(n-m,m) & \text{, } n>m>1 \end{cases} q(n,m)= 1q(n,n)1+q(n,n1)q(n,m1)+q(nm,m)n1,m=1n<mn=mn>m>1

求正整数n的不同划分个数,即求正整数n的划分数p(n)=q(n,n)。

根据分析结果写动态规划求解的递推公式

我们使用二维数组 d p [ i ] [ j ] dp[i][j] dp[i][j],记录划分整数i且最大划分不超过j的最大划分个数,则递推公式为:
d p [ i ] [ j ] = { 1 ,  i ≥ 1 , j = 1 d p [ i ] [ i ] ,  i < j 1 + d p [ i − j ] [ j ] ,  i = j d p [ i ] [ j − 1 ] + d p [ i − j ] [ j ] ,  i > j > 1 dp[i][j]=\begin{cases} 1 & \text{, } i \geq 1,j=1 \\dp[i][i] & \text{, } i < j & \\1 + dp[i-j][j] & \text{, } i = j \\dp[i][j-1]+dp[i-j][j] & \text{, } i>j>1 \end{cases} dp[i][j]= 1dp[i][i]1+dp[ij][j]dp[i][j1]+dp[ij][j]i1,j=1i<ji=ji>j>1

4. 以自底向上方式计算最优值💻

基于递推关系式,用二维数组存储 d p [ i ] [ j ] dp[i][j] dp[i][j]的结果,通过填记录最优值的表求解。以下为实现步骤:

#include <stdio.h>#define MAX_N 100 // 设置最大 n 的范围// 动态规划函数:计算整数划分
int integerPartition(int n)
{int dp[MAX_N + 1][MAX_N + 1] = {0}; // 初始化动态规划数组// 初始化边界条件for (int i = 0; i <= n; i++){dp[i][1] = 1; // 最大加数m为 1 时,只有一种划分方式}for (int i = 1; i <= n; i++){for (int j = 2; j <= n; j++){if (i < j){dp[i][j] = dp[i][i]; // n < m 的情况}else if (i == j){dp[i][j] = 1 + dp[i][i - 1]; // n == m 的情况}else{dp[i][j] = dp[i][j - 1] + dp[i - j][j]; //  n>m>1的情况,转移方程}}}return dp[n][n]; // 返回最终结果
}int main()
{int n;printf("请输入正整数 n:");scanf("%d", &n);int res = integerPartition(n);printf("正整数 %d 的划分数是:%d\n", n, res);return 0;
}

运行结果:
在这里插入图片描述


5. 优化 📊

问题回顾

我们需要计算将正整数 n n n 划分为一系列正整数之和的划分数。例如, n = 4 n = 4 n=4 的划分数为 5,划分方式为:

4
3 + 1
2 + 2
2 + 1 + 1
1 + 1 + 1 + 1

原始二维动态规划

在原始代码中,我们使用了一个二维数组 dp[i][j],其中:

  • dp[i][j] 表示将整数 i i i 划分为最大加数不超过 j j j 的划分数。

递推公式为:

  1. 如果 i < j i < j i<j,则 dp[i][j] = dp[i][i]
  2. 如果 i = j i = j i=j,则 dp[i][j] = 1 + dp[i][j - 1]
  3. 如果 i > j i > j i>j,则 dp[i][j] = dp[i][j - 1] + dp[i - j][j]

这个递推公式的核心思想是:

  • 将划分分为两类:不包含 j j j 的划分包含 j j j 的划分
    • 不包含 j j j 的划分数是 dp[i][j - 1]
    • 包含 j j j 的划分数是 dp[i - j][j]

优化为一维动态规划

我们观察到,二维数组 dp[i][j] 的更新只依赖于当前行上一行的值。具体来说:

  • 在计算 dp[i][j] 时,只需要 dp[i][j - 1]dp[i - j][j]
  • 这意味着我们可以用一维数组 dp[i] 来存储当前行的值,并通过滚动更新的方式计算。

实际上,二维动态规划的依赖关系是:
dp[i][j] 依赖于:

  1. dp[i][j−1](当前行的前一个值)。
  2. dp[i−j][j](上一行的某个值)。

这种依赖关系并不是简单的“当前行和上一行”,而是涉及到了更复杂的跳跃依赖(因为 dp[i−j][j] 的位置与 dp[i][j] 的位置相差 j 行)。

为什么可以优化为一维数组?
尽管依赖关系复杂,但我们仍然可以优化为一维数组,原因如下:

  1. 滚动更新的思想:

在计算 dp[i][j] 时,我们只需要 dp[i][j−1] 和 dp[i−j][j]。

如果我们按照一定的顺序更新 dp[i],可以确保在计算 dp[i] 时,dp[i−j] 已经被正确更新。

  1. 枚举顺序的调整:

在优化后的代码中,我们首先枚举最大加数 j(从 1 到 n),然后枚举目标数 i(从 j 到 n)。

这种枚举顺序确保了在计算 dp[i] 时,dp[i−j] 已经被正确更新。

  1. 一维数组的含义:

优化后的一维数组 dp[i] 表示将整数 i 划分为一系列正整数之和的划分数。

在枚举 j 时,我们逐步更新 dp[i],使其包含所有可能的划分。


优化后的递推公式

优化后的递推公式为:
d p [ i ] = d p [ i ] + d p [ i − j ] dp[i] = dp[i] + dp[i - j] dp[i]=dp[i]+dp[ij]
其中:

  • dp[i] 表示将整数 i i i 划分为一系列正整数之和的划分数。
  • j 是当前枚举的最大加数。
递推公式的推导
  1. 初始化

    • dp[0] = 1,表示空划分(即不选任何数)。
  2. 枚举最大加数 j j j

    • 对于每个 j j j(从 1 到 n n n),我们更新 dp[i] 的值。
    • 更新规则:dp[i] += dp[i - j]
  3. 解释更新规则

    • dp[i] 表示将 i i i划分为一系列正整数之和的划分数。
    • dp[i - j] 表示将 i − j i - j ij 划分为一系列正整数之和的划分数。
    • 当我们加上 dp[i - j] 时,实际上是在考虑所有包含 j j j 的划分。
    • 例如,如果 j = 2 j = 2 j=2,那么 dp[i] += dp[i - 2] 表示将 i i i 划分为包含 2 的划分数。
  4. 为什么可以这样更新

    • 在原始二维动态规划中,dp[i][j] = dp[i][j - 1] + dp[i - j][j]
    • 优化后的一维动态规划中,dp[i] 相当于 dp[i][j],而 dp[i - j] 相当于 dp[i - j][j]
    • 通过滚动更新,dp[i] 的值会逐步累积,最终得到正确的结果。

示例演示

n = 4 n = 4 n=4 为例,演示优化后的动态规划过程:

  1. 初始化

    • dp = [1, 0, 0, 0, 0],其中 dp[0] = 1
  2. 枚举 j = 1 j = 1 j=1

    • 更新 dp[i] 的值:
      • dp[1] += dp[0]dp[1] = 1
      • dp[2] += dp[1]dp[2] = 1
      • dp[3] += dp[2]dp[3] = 1
      • dp[4] += dp[3]dp[4] = 1
    • 此时 dp = [1, 1, 1, 1, 1]
  3. 枚举 j = 2 j = 2 j=2

    • 更新 dp[i] 的值:
      • dp[2] += dp[0]dp[2] = 1 + 1 = 2
      • dp[3] += dp[1]dp[3] = 1 + 1 = 2
      • dp[4] += dp[2]dp[4] = 1 + 2 = 3
    • 此时 dp = [1, 1, 2, 2, 3]
  4. 枚举 j = 3 j = 3 j=3

    • 更新 dp[i] 的值:
      • dp[3] += dp[0]dp[3] = 2 + 1 = 3
      • dp[4] += dp[1]dp[4] = 3 + 1 = 4
    • 此时 dp = [1, 1, 2, 3, 4]
  5. 枚举 j = 4 j = 4 j=4

    • 更新 dp[i] 的值:
      • dp[4] += dp[0]dp[4] = 4 + 1 = 5
    • 此时 dp = [1, 1, 2, 3, 5]

最终,dp[4] = 5,即 n = 4 n = 4 n=4 的划分数为 5。


实现优化后的程序

#include <stdio.h>#define MAX_N 100 // 设置最大 n 的范围// 动态规划函数:计算整数划分
int integerPartition(int n)
{int dp[MAX_N + 1] = {0}; // 初始化一维动态规划数组dp[0] = 1; // 初始化 dp[0] = 1,表示空划分for (int j = 1; j <= n; j++) // 枚举最大加数 j{for (int i = j; i <= n; i++) // 枚举目标数 i{dp[i] += dp[i - j]; // 转移方程:dp[i] = dp[i] + dp[i - j]}}return dp[n]; // 返回最终结果
}int main()
{int n;printf("请输入正整数 n:");scanf("%d", &n);int res = integerPartition(n);printf("正整数 %d 的划分数是:%d\n", n, res);return 0;
}

优化总结

通过分析原始二维动态规划的递推公式,我们发现:

  • 只需要一维数组即可存储中间结果。
  • 通过枚举最大加数 j j j 并更新 dp[i],可以逐步计算出划分数。

优化后的递推公式为:
d p [ i ] = d p [ i ] + d p [ i − j ] dp[i] = dp[i] + dp[i - j] dp[i]=dp[i]+dp[ij]
这种方法不仅减少了空间复杂度,还保持了相同的时间复杂度 O ( n 2 ) O(n^2) O(n2)


6. 扩展思考 🎯

6.1 相关问题

  1. 完全背包问题
  2. 硬币找零问题
  3. 数字组合问题

6.2 实际应用场景

  1. 财务系统中的支付方案设计
  2. 资源分配问题
  3. 任务调度优化

7. 练习建议 📝

  1. 先从小规模问题入手,手动推导
  2. 画图辅助理解状态转移
  3. 多关注边界条件的处理
  4. 尝试不同的实现方式,比较优劣

总结 🎉

整数划分问题是一个非常经典的动态规划问题,通过本文的学习,我们不仅掌握了问题的解决方法,更重要的是理解了动态规划的思维方式和优化技巧:整数划分问题通过动态规划实现,将问题分解为子问题求解。
通过学习和实现这个问题,能够深入理解动态规划的核心思想,掌握处理类似问题的技巧。✨

希望本文对你有所帮助!💖
🎉 Happy Coding!


🤔 思考题

  1. 如何修改代码来输出所有的划分方案?
  2. 如果限制划分中数字不能重复使用,应该如何修改算法?
  3. 如果要求划分中的数字必须是奇数,如何调整递推公式?

欢迎在评论区分享你的想法和解答!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Elasticsearch7.11】postman批量导入少量数据

JSON 文件内的数据格式&#xff0c;json文件数据条数不要过多&#xff0c;会请求参数过大&#xff0c;最好控制再10000以内。 {"index":{"_id":"baec07466732902d22a24ba01ff09751"}} {"uuid":"baec07466732902d22a24ba01ff0975…

Mysql--架构篇--体系结构(连接层,SQL层,存储引擎层,文件存储层)

MySQL是一种广泛使用的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;其体系结构设计旨在提供高效的数据存储、查询处理和事务管理。MySQL的体系结构可以分为多个层次&#xff0c;每个层次负责不同的功能模块。 MySQL的体系结构主要由以下几个部分组成&#…

ue5 蒙太奇,即上半身动画和下半身组合在一起,并使用。学习b站库得科技

本文核心 正常跑步动画端枪动画跑起来也端枪 正常跑步动画 端枪动画的上半身 跑起来也端枪 三步走&#xff1a; 第一步制作动画蒙太奇和插槽 第二步动画蓝图选择使用上半身动画还是全身动画&#xff0c;将上半身端枪和下半身走路结合 第三步使用动画蒙太奇 1.开始把&a…

Linux下部署Redis(本地部署超详细)

非docker 1、下载Redis 历史版本&#xff1a; http://download.redis.io/releases 我的&#xff1a; http://download.redis.io/releases/redis-7.0.5.tar.gz 2.安装教程 1.Redis是基于c语言编写的需要安装依赖&#xff0c;需要安装gcc yum install gcc-c 2.查看gcc版…

java -jar启动项目报错:XXX.jar中没有主清单属性

XXX.jar中没有主清单属性 1、错误复现2、错误原因3、解决方案 java -jar启动项目报错&#xff1a;XXX.jar中没有主清单属性 1、错误复现 今天使用springboot给项目打了jar包&#xff0c;使用命令启动时报错&#xff0c;截图如下&#xff1a; 2、错误原因 项目的pom文件配置如…

贪心算法详细讲解(沉淀中)

文章目录 1. 什么是贪心算法&#xff1f;&#xff08;贪婪鼠目寸光&#xff09;经典例题1.1.1 找零问题1.1.2最小路径和1.1.3 背包问题 2.贪心算法的特点2.1 证明例1 3.学习贪心的方向心得体会 1. 什么是贪心算法&#xff1f;&#xff08;贪婪鼠目寸光&#xff09; 贪心策略&a…

【Logstash03】企业级日志分析系统ELK之Logstash 过滤 Filter 插件

Logstash 过滤 Filter 插件 数据从源传输到存储库的过程中&#xff0c;Logstash 过滤器能够解析各个事件&#xff0c;识别已命名的字段以构建结构&#xff0c; 并将它们转换成通用格式&#xff0c;以便进行更强大的分析和实现商业价值。 Logstash 能够动态地转换和解析数据&a…

unity打包sdk热更新笔记

基础打包需要知识&#xff1a; 安装包大小不要超过2G&#xff0c;AB包数量过多会影响加载和构建&#xff0c;多次IO&#xff0c;用Gradle打包&#xff0c;要支持64位系统&#xff0c;不同的渠道包&#xff1a;让做sdk的人支持&#xff0c;提供渠道包的打包工具 配置系统环境变量…

论文笔记(六十一)Implicit Behavioral Cloning

Implicit Behavioral Cloning 文章概括摘要1 引言2 背景&#xff1a;隐式模型的训练与推理3 隐式模型与显式模型的有趣属性4 policy学习成果5 理论见解&#xff1a;隐式模型的通用逼近性6 相关工作7 结论 文章概括 引用&#xff1a; inproceedings{florence2022implicit,titl…

【Rust自学】12.3. 重构 Pt.1:改善模块化

12.3.0. 写在正文之前 第12章要做一个实例的项目——一个命令行程序。这个程序是一个grep(Global Regular Expression Print)&#xff0c;是一个全局正则搜索和输出的工具。它的功能是在指定的文件中搜索出指定的文字。 这个项目分为这么几步&#xff1a; 接收命令行参数读取…

Vue2+OpenLayers调用WMTS服务初始化天地图示例(提供Gitee源码)

目录 一、案例截图 二、安装OpenLayers库 三、WMTS服务详解 四、完整代码 五、Gitee源码 一、案例截图 二、安装OpenLayers库 npm install ol 三、WMTS服务详解 WMTS&#xff08;Web Map Tile Service&#xff09;是一种标准的网络地图服务协议&#xff0c;用于提供基于…

【STM32-学习笔记-6-】DMA

文章目录 DMAⅠ、DMA框图Ⅱ、DMA基本结构Ⅲ、不同外设的DMA请求Ⅳ、DMA函数Ⅴ、DMA_InitTypeDef结构体参数①、DMA_PeripheralBaseAddr②、DMA_PeripheralDataSize③、DMA_PeripheralInc④、DMA_MemoryBaseAddr⑤、DMA_MemoryDataSize⑥、DMA_MemoryInc⑦、DMA_DIR⑧、DMA_Buff…

lerna使用指南

lerna版本 以下所有配置命令都是基于v8.1.9&#xff0c;lerna v5 v7版本差别较大&#xff0c;在使用时&#xff0c;注意自身的lerna版本。 lerna开启缓存及缓存配置 nx缓存是v5版本以后才有的&#xff0c;小于该版本的无法使用该功能。 初始化配置 缓存配置文件nx.json&am…

html辅助标签与样式表

一、HTML其它常用标签 1.meta标签 &#xff08;1&#xff09;meta标签是一个特殊的HTML标签&#xff0c;提供有关网页的信息&#xff0c;如作者姓名、公司名称和联系信息等 &#xff08;2&#xff09;许多搜索引擎都使用meta标签 <head> <meta name"keyword…

用 Python 从零开始创建神经网络(十九):真实数据集

真实数据集 引言数据准备数据加载数据预处理数据洗牌批次&#xff08;Batches&#xff09;训练&#xff08;Training&#xff09;到目前为止的全部代码&#xff1a; 引言 在实践中&#xff0c;深度学习通常涉及庞大的数据集&#xff08;通常以TB甚至更多为单位&#xff09;&am…

DolphinScheduler自身容错导致的服务器持续崩溃重大问题的排查与解决

01 问题复现 在DolphinScheduler中有如下一个Shell任务&#xff1a; current_timestamp() { date "%Y-%m-%d %H:%M:%S" }TIMESTAMP$(current_timestamp) echo $TIMESTAMP sleep 60 在DolphinScheduler将工作流执行策略设置为并行&#xff1a; 定时周期调度设置…

【机器学习案列】学生抑郁可视化及预测分析

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

Docker Desktop 构建java8基础镜像jdk安装配置失效解决

Docker Desktop 构建java8基础镜像jdk安装配置失效解决 文章目录 1.问题2.解决方法3.总结 1.问题 之前的好几篇文章中分享了在Linux(centOs上)和windows10上使用docker和docker Desktop环境构建java8的最小jre基础镜像&#xff0c;前几天我使用Docker Desktop环境重新构建了一个…

【Uniapp-Vue3】页面生命周期onLoad和onReady

一、onLoad函数 onLoad在页面载入时触发&#xff0c;多用于页面跳转时进行参数传递。 我们在跳转的时候传递参数name和age: 接受参数&#xff1a; import {onLoad} from "dcloudio/uni-app"; onLoad((e)>{...}) 二、onReady函数 页面生命周期函数中的onReady其…

【STM32-学习笔记-8-】I2C通信

文章目录 I2C通信Ⅰ、硬件电路Ⅱ、IIC时序基本单元① 起始条件② 终止条件③ 发送一个字节④ 接收一个字节⑤ 发送应答⑥ 接收应答 Ⅲ、IIC时序① 指定地址写② 当前地址读③ 指定地址读 Ⅳ、MPU6050---6轴姿态传感器&#xff08;软件I2C&#xff09;1、模块内部电路2、寄存器地…