一个人内耗,说明他活在过去;一个人焦虑,说明他活在未来。只有当一个人平静时,他才活在现在。
日常
1、起床6:00
2、健身2h
3、LeetCode刷了1题
- 动态规划:01背包理论基础
- 掌握01背包和完全背包,就够用了,最多可以再来一个多重背包。
- 完全背包又是也是01背包稍作变化而来,即:完全背包的物品数量是无限的。01背包是每个物品数量只有一个
- 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是
weight[i]
,得到的价值是value[i]
。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。 - 那么暴力的解法应该是怎么样的呢?每一件物品其实只有两个状态,取或者不取,所以可以使用回溯法搜索出所有的情况,那么时间复杂度就是O(2^n),这里的n表示物品数量。
- 二维dp数组01背包:动规五部曲分析一波
- 确定dp数组以及下标的含义:我们需要使用二维数组,为什么呢?因为有两个维度需要分别表示:物品 和 背包容量,二维数组为
dp[i][j]
;i 来表示物品、j表示背包容量。dp[i][j]
表示共i个物品和j的容量的最大价值 = Math.max(放入i的最大价值dp[i-1][j-w[i]]+v[i]
,不放入i的最大价值dp[i-1][j])
- 确定递推公式:
dp[i][j]
表示i个物品和j的容量的最大价值 = Math.max(放入i后的最大价值dp[i-1][j-w[i]]+v[i]
,不放入i的最大价值dp[i-1][j])
- 初始化dp数组:刚开始初始化时,只需要根据每个物品的价值和重量,将当前物品单独放入后初始化数组即可,即对于每一行i,当容量大于i物品的重量时,就令元素为i的价值,否则为0,且第一行第一列一定要进行初始化,第一列全部为0,因为背包容量为0,第一行根据第一个物品的价值进行初始化
- 确认遍历顺序:根据递推公式,要从前向后、从上向下遍历,可以先遍历物品再遍历背包,也可以先遍历背包再遍历物品,虽然两个for循环遍历的次序不同,但是
dp[i][j]
所需要的数据就是左上角,根本不影响dp[i][j]
公式的推导! - 举例判断:如果出错则打印dp数组看是否符合预期
- 确定dp数组以及下标的含义:我们需要使用二维数组,为什么呢?因为有两个维度需要分别表示:物品 和 背包容量,二维数组为
- 滚动数组(
dp[i]表示背包容量
)- 就是把二维dp降为一维dp,因为二维dp是从前向后从上向下的,故可以使用一维dp来节省空间
- 对于背包问题其实状态都是可以压缩的。
- 可以发现如果把
dp[i - 1]
那一层拷贝到dp[i]
上,表达式完全可以是:dp[i][j]
=max(dp[i][j], dp[i][j - weight[i]] + value[i])
;与其把dp[i - 1]
这一层拷贝到dp[i]
上,不如只用一个一维数组了,只用dp[j]
(一维数组,也可以理解是一个滚动数组)。j表示背包容量为j是可以存放的最大价值 - 滚动数组需要满足的条件是上一层可以重复利用,直接拷贝到当前层
- 此时的递推公式为:
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
- dp数组初始化的时候,都初始为0就可以了,或者初始化为第一个物品放入后的价值
- 一维数组时,必须先遍历背包容量,即外出循环是物品,内层循环是背包容量,必须先从前到后遍历然后再从上向下遍历,故必须先遍历背包容量,外层是物品
- 倒序遍历:二维dp遍历的时候,背包容量是从小到大,而一维dp遍历的时候,背包是从大到小,背包里只放入了一个物品
- 使用一维dp数组的写法,比较直观简洁,而且空间复杂度还降了一个数量级
- 要求先实现一个纯二维的01背包,如果写出来了,然后再问为什么两个for循环的嵌套顺序这么写?反过来写行不行?(二维数组遍历顺序不影响,因为只依赖左上方的元素),再讲一讲初始化的逻辑。然后要求实现一个一维数组的01背包,最后再问,一维数组的01背包,两个for循环的顺序反过来写行不行?为什么? 不可以,因为一维必须每加一个物品就遍历一行背包容量,每加一个物品要在前面背包的基础上更新
- 分割等和子集
- 先求出总sum,为奇数直接返回false,然后看最大元素是否超过了 sum / 2,超过了直接返回false,否则就是要动图规划dp进行判断,使用一维dp,外层循环是元素
- 背包的体积为sum / 2
- 背包要放入的商品(集合里的元素)重量为 元素的数值,价值也为元素的数值
- 背包如果正好装满(价值等于重量),说明找到了总和为 sum / 2 的子集。
- 背包中每一个元素是不可重复放入。
- 递推公式:
dp[j] = max(dp[j], dp[j - nums[j]] + nums[j])
- 如果使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环放在内层,且内层for循环倒序遍历
- 每个物品的价值等于重量,如果正好装满则说明存在子集
4、复盘22:00
不复盘等于白学!!!
学习和感想
Kubernetes学习
1. Kubernetes
- 存储抽象
- 存储抽象就是实现多个集群机器中的存储共享
- NFS文件系统实现挂载
存储抽象就是实现多个集群机器中的存储共享,可以通过NFS文件系统进行实现,此时需要每个机器都先安装NFS文件系统,任何主节点将其创建的共享文件暴露出去,从节点将自己的某个目录与主节点暴露的目录挂载起来,此时就可以实现目录共享,从而实现存储共享
NFS文件系统就是在一个集群中多个机器中实现一个共享文件,此时集群中容器就可以挂载到NFS文件系统中,从而实现数据存储更加安全,因为被同时保存在多个机器中
k8s将每个pod挂载的目录抽象出来,形成存储层
可以使用NFS文件系统实现存储抽象,NFS文件系统环境配置
k8s基于NFS实现数据挂载,通过以下配置创建的deployement中的容器会将指定的文件挂载到配置的NFS文件系统中存储共享的文件中,此时容器挂载的文件会通过NFS文件系统被共享到每台机器中,且多个容器中文件可以挂载到同一个数据卷中
要挂载到NFS文件系统中,则必须在NFS文件系统中创建指定的目录,只有目录存在时才可以挂载
NFS文件系统的挂载,当容器删除之后,其挂载的文件(NFS中)不会被删除,且每个容器挂载的文件不会被限制
- PV&PVC持久卷(静态/动态供应)
PV:持久卷,将应用需要持久化的数据保存到指定位置
PVC:持久卷申明,申明需要使用的持久卷的规格,即文件大小
PV&PVC:此时pod需要持久化数据挂载时,通过PVC申请一块持久化空间PV,并指定空间大小,然后就可以实现数据持久化挂载,然后当pod结束时,就会删除PVC并回收分配的PV,从而取消挂载
使用PVC申请PV时,会根据申请的空间大小分配一个合适的PV,且一个PV只可以被一个PVC申请,同一个PV只可以被一个PVC申请
先创建PVC申请PV,然后在创建pod时指定所创建的PVC,此时就会在指定的PV中进行数据持久化
- ConfigMap
挂载目录推荐使用PV&PVC,因为此时当pod删除时也会释放其上挂载的PVC,且可以指定分配的空间
但PV&PVC主要用于挂载目录,对于配置文件,推荐使用ConfigMap进行挂载
可以使用ConfigMap单独挂载配置文件
可以通过 kubectl create cm cmName --from-file=xxx.conf 将pod的配置文件单独创建为一个配置集cm(ConfigMap),此时会存放在k8s的etcd中进保存,此时启动容器时,就可以使用配置集中的配置文件进行启动
使用创建的配置集来启动pod容器
且使用ConfigMap来挂载配置文件时,此时对CM修改会直接同步更新容器内部的配置文件,修改ConfigMap会自动修改挂载改cm的pod容器内部的配置文件,但不会生效,因为**配置文件修改后必须重启才会生效
- Secret
- Secret对象类型用来保存敏感信息,将这些信息放在Secret中比放在pod的定义或者容器镜像中更加安全灵活
- 就比如当创建pod时要从私有镜像库中拉取镜像,此时需要密码权限才可以拉取,如果直接在pod的yaml文件中配置密码是很不安全的,故可以将密码放到Secret中保存,此时就可以通过在yaml配置文件中配置Secret来进行访问
2. KubeSphere
- 简介+安装
- KubeSphere平台基于Kubenetes构建的分布式、多租户、多集群、企业级开源平台,有强大且完善的网络与存储能力,并通过极简的人机交互提供完善的管理
- 在 www.kubeshere.com.cn 官网中进行安装,可以在Kubernetes或者Linux中进行安装
- 在Kubernetes中安装KubeSphere,前提是安装好Kubernetes集群
- 当Kubernetes安装完成后就可以安装KubeSphere前置环境