底层自行实现——监督学习算法(1线性回归)

1.1 简单线性回归

1. 简介

简单线性回归(SLR - Simple Linear Regression)模型可以表示为: Y = β 0 + β 1 X + ϵ Y = \beta_0 + \beta_1X + \epsilon Y=β0+β1X+ϵ

  • Y Y Y:因变量或目标变量。
  • X X X:自变量或解释变量。
  • β 0 \beta_0 β0:截距项,是当 X = 0 X=0 X=0 Y Y Y的期望值。
  • β 1 \beta_1 β1:斜率项,表示 X X X每变化一个单位, Y Y Y变化的量。
  • ϵ \epsilon ϵ​:误差项,表示模型未能解释的随机变异。

关于 ϵ \epsilon ϵ的解释

假设你是一位经济学家,正在研究家庭年收入(因变量 Y Y Y)与家庭主要收入者的教育年数(解释变量 X X X)之间的关系。你决定使用简单线性回归模型来分析这两个变量之间的关系。模型可以表示为: Y = β 0 + β 1 X + ϵ Y = \beta_0 + \beta_1X + \epsilon Y=β0+β1X+ϵ其中:

  • Y Y Y 表示家庭年收入。
  • X X X 表示家庭主要收入者的教育年数。
  • β 0 \beta_0 β0 是截距项,代表了当教育年数为0时预期的家庭年收入。
  • β 1 \beta_1 β1 是斜率项,表示教育年数每增加一年,家庭年收入平均增加的金额。
  • ϵ \epsilon ϵ 是误差项,代表了除了教育年数之外影响家庭年收入的所有其他因素。

例子说明

在现实中,家庭年收入受到多种因素的影响,除了教育年数之外,还可能包括行业、工作经验、地区、经济环境、健康状况等。由于我们的模型仅考虑了教育年数这一变量,因此模型无法完全解释家庭年收入的所有变化。这些未被模型捕捉的因素就通过误差项 ϵ \epsilon ϵ 来表示。

2. 例子与底层的手动实现

现在我们根据一个例子来深入理解简单线性回归。

**题目描述:**假设你是一位经济学家,正在研究家庭年收入(因变量 Y Y Y)与家庭主要收入者的教育年数(解释变量 X X X)之间的关系。你决定使用简单线性回归模型来分析这两个变量之间的关系。你收集了 10 个家庭的数据,如下所示:
[10, 12, 8, 15, 16, 18, 20, 14, 15, 11, 15, 19, 20]
[40, 45, 32, 50, 55, 65, 75, 48, 50, 38, 52, 70, 80]

将其使用散点图显示如下:

在这里插入图片描述

那么不使用scikit-learn库,手动实现简单线性回归,想一想如果想要用一条直线拟合这些点,我们需要计算些什么?

大家应该都很了解直线**,要确定一条直线,需要一个斜率,需要一个截距。**在这里我们就需要提到最小二乘法。

最小二乘法(Least Squares Method)

最小二乘法是一种常用的数学优化方法,用于求解线性回归等问题中的最优参数。其核心思想是通过最小化观测数据与模型预测之间的残差平方和来估计参数。

在线性回归问题中,假设我们有一组观测数据 ( x i , y i ) (x_i, y_i) (xi,yi),其中 x i x_i xi 是自变量(特征), y i y_i yi 是因变量(目标值)。我们希望找到一个线性模型 y = f ( x ) y = f(x) y=f(x),其中 f ( x ) f(x) f(x) 是关于 x x x 的线性函数,使得模型预测值 f ( x i ) f(x_i) f(xi) 与观测值 y i y_i yi 之间的误差最小化。最小二乘法通过求解以下优化问题来找到最优的模型参数:

min ⁡ β ∑ i = 1 n ( y i − f ( x i ; β ) ) 2 \min_{\beta} \sum_{i=1}^{n} (y_i - f(x_i; \beta))^2 βmini=1n(yif(xi;β))2

其中 β \beta β 是模型的参数, f ( x i ; β ) f(x_i; \beta) f(xi;β) 是模型对 x i x_i xi 的预测值。优化问题的目标是使残差的平方和最小化,即使得模型预测值与观测值之间的误差尽可能小。


假设我们有一组观测数据 ( x i , y i ) (x_i, y_i) (xi,yi),其中 x i x_i xi 是自变量(特征), y i y_i yi 是因变量(目标值)。我们希望找到一个线性模型 y = m x + b y = mx + b y=mx+b,其中 m m m 是斜率, b b b​ 是截距,使得模型预测值与观测值之间的误差最小化。

以下为推理过程,实际上就是最小二乘法:

步骤1

首先,我们定义残差 e i e_i ei 为观测值 y i y_i yi 与模型预测值 m x i + b mx_i + b mxi+b 之间的差异:
e i = y i − ( m x i + b ) e_i = y_i - (mx_i + b) ei=yi(mxi+b)

我们的目标是使残差的平方和最小化,即求解下面的优化问题:

min ⁡ m , b ∑ i = 1 n e i 2 \min_{m, b} \sum_{i=1}^{n} e_i^2 m,bmini=1nei2

其实也就是:
min ⁡ β ∑ i = 1 n ( y i − ( m x i + b ) ) 2 \min_{\beta} \sum_{i=1}^{n} (y_i - (mx_i + b))^2 βmini=1n(yi(mxi+b))2

步骤2

如何寻找函数的极值点?

  1. 确定函数的定义域:首先,需要知道函数在哪个区间或集合上是定义的,因为极值点必须在函数的定义域内。

  2. 求导:计算函数的一阶导数。这是因为在极值点处,函数的导数为零或导数不存在。一阶导数告诉我们函数在某点处的瞬时变化率。

  3. 解方程找临界点:将一阶导数等于零,解这个方程找到所有可能的临界点。临界点是函数导数为零或导数不存在的点,函数在这些点可能有极值。

  4. 二阶导数测试(如果需要):为了确定这些临界点是否为极值点,可以使用二阶导数测试。如果某个临界点处的二阶导数大于零,则该点是局部最小值;如果二阶导数小于零,则该点是局部最大值;如果二阶导数等于零,则测试无法判定,可能需要进一步的分析。

  5. 边界点检查:如果函数在闭区间上定义,还需要检查区间的端点,因为极值也可能出现在边界上。

  6. 比较值:计算所有临界点和边界点处的函数值,以确定全局最大值和最小值(如果题目要求)。

通过这些步骤,就可以找到函数在其定义域内的所有局部极大值和极小值点,以及可能的全局极值点。

因为在极值点处,函数的导数为零或导数不存在,我们现在需要找到上述公式的极小值,也就是为了最小化这个目标函数,**(记住,此时我们需要将斜率m和截距b当作未知,因为这是我们需要求解的参数,我们要查看这两个值对于损失也就是残差的平方和的影响)**我们需要对 m m m b b b 分别求偏导,并令偏导数等于零(因为这是一个二次函数,且定义域为实数集,所以通过求解其偏导数为零的点,即找到损失函数的极值点,从而得到最优的模型参数)。

b b b 求偏导得到:
∂ ∂ b ∑ i = 1 n e i 2 = − 2 ∑ i = 1 n ( y i − ( m x i + b ) ) = 0 \frac{\partial}{\partial b} \sum_{i=1}^{n} e_i^2 = -2 \sum_{i=1}^{n} (y_i - (mx_i + b)) = 0 bi=1nei2=2i=1n(yi(mxi+b))=0

整理得到:

∑ i = 1 n ( y i − ( m x i + b ) ) = 0 \sum_{i=1}^{n} (y_i - (mx_i + b)) = 0 i=1n(yi(mxi+b))=0

进一步整理,我们得到:

∑ i = 1 n ( y i − m x i − b ) = 0 ( 1 ) \sum_{i=1}^{n} (y_i - mx_i - b) = 0 \space\space\space\space\space\space\space\space(1) i=1n(yimxib)=0        (1)

m m m 求偏导得到:
∂ ∂ m ∑ i = 1 n e i 2 = − 2 ∑ i = 1 n x i ( y i − ( m x i + b ) ) = 0 \frac{\partial}{\partial m} \sum_{i=1}^{n} e_i^2 = -2 \sum_{i=1}^{n} x_i(y_i - (mx_i + b)) = 0 mi=1nei2=2i=1nxi(yi(mxi+b))=0

整理得到:

∑ i = 1 n ( x i y i − m x i 2 − b x i ) = 0 ( 2 ) \sum_{i=1}^{n} (x_iy_i - mx_i^2 - bx_i) = 0\space\space\space\space\space\space\space\space(2) i=1n(xiyimxi2bxi)=0        (2)

步骤3

现在我们有(1)(2)两个方程,可以根据(1)和(2)得到如下的方程组:
∑ i = 1 n x i y i − m ∑ i = 1 n x i 2 − b ∑ i = 1 n x i = 0 ∑ i = 1 n y i − m ∑ i = 1 n x i − n b = 0 \begin{align*} \sum_{i=1}^{n} x_iy_i - m\sum_{i=1}^{n} x_i^2 - b\sum_{i=1}^{n} x_i &= 0 \\ \sum_{i=1}^{n} y_i - m\sum_{i=1}^{n} x_i - nb &= 0 \end{align*} i=1nxiyimi=1nxi2bi=1nxii=1nyimi=1nxinb=0=0
这是一个线性方程组,我们可以通过解这个方程组找到 a a a b b b的值。

为了求解 m m m,我们先从第二个方程开始,表达 b b b
n b = ∑ y i − m ∑ x i b = ∑ y i n − m ∑ x i n b = y ˉ − m x ˉ nb = \sum y_i - m\sum x_i\\ b = \frac{\sum y_i}{n} - m\frac{\sum x_i}{n}\\ b = \bar{y} - m\bar{x} nb=yimxib=nyimnxib=yˉmxˉ
其中, x ˉ \bar{x} xˉ y ˉ \bar{y} yˉ 分别是 x i x_i xi y i y_i yi 的均值。

接下来,将 b b b 的表达式代入第一个方程中:
m ∑ x i 2 + ( y ˉ − m x ˉ ) ∑ x i = ∑ x i y i m\sum x_i^2 + \left(\bar{y} - m\bar{x}\right)\sum x_i = \sum x_iy_i mxi2+(yˉmxˉ)xi=xiyi
这可以重新整理为:
m ∑ x i 2 − m x ˉ ∑ x i + y ˉ ∑ x i = ∑ x i y i m\sum x_i^2 - m\bar{x}\sum x_i + \bar{y}\sum x_i = \sum x_iy_i mxi2mxˉxi+yˉxi=xiyi
因为 ∑ x i = n x ˉ \sum x_i = n\bar{x} xi=nxˉ,所以方程进一步简化为:
m ∑ x i 2 − m n x ˉ 2 + n x ˉ y ˉ = ∑ x i y i m\sum x_i^2 - mn\bar{x}^2 + n\bar{x}\bar{y} = \sum x_iy_i mxi2mnxˉ2+nxˉyˉ=xiyi
然后,我们解 m m m
m ( ∑ x i 2 − n x ˉ 2 ) = ∑ x i y i − n x ˉ y ˉ m = ∑ x i y i − n x ˉ y ˉ ∑ x i 2 − n x ˉ 2 m(\sum x_i^2 - n\bar{x}^2) = \sum x_iy_i - n\bar{x}\bar{y} \\m = \frac{\sum x_iy_i - n\bar{x}\bar{y}}{\sum x_i^2 - n\bar{x}^2} m(xi2nxˉ2)=xiyinxˉyˉm=xi2nxˉ2xiyinxˉyˉ
因为如下两个式子等价:
∑ ( x i − x ˉ ) ( y i − y ˉ ) = ∑ x i y i − y ˉ ∑ x i − x ˉ ∑ y i + n x ˉ y ˉ = ∑ x i y i − n x ˉ y ˉ − n x ˉ y ˉ + n x ˉ y ˉ = ∑ x i y i − n x ˉ y ˉ \sum (x_i - \bar{x})(y_i - \bar{y}) \\= \sum x_iy_i - \bar{y}\sum x_i - \bar{x}\sum y_i + n\bar{x}\bar{y}\\ = \sum x_iy_i - n\bar{x}\bar{y} - n\bar{x}\bar{y} + n\bar{x}\bar{y}\\ =\sum x_iy_i - n\bar{x}\bar{y} (xixˉ)(yiyˉ)=xiyiyˉxixˉyi+nxˉyˉ=xiyinxˉyˉnxˉyˉ+nxˉyˉ=xiyinxˉyˉ
所以我们就相当于处理完了分子。现在我们再处理分母
∑ ( x i − x ˉ ) 2 = ∑ ( x i 2 − 2 ∑ x i x ˉ + ∑ x ˉ 2 ) = ∑ x i 2 − 2 n x ˉ + n x ˉ 2 = ∑ x i 2 − n x ˉ \sum(x_i - \bar{x})^2\\=\sum(x_i^2 - 2 \sum{x_i}\bar{x} + \sum{\bar{x}^2})\\ =\sum{x_i^2} - 2 n\bar{x} + n\bar{x}^2 \\=\sum{x_i^2} - n\bar{x} (xixˉ)2=(xi22xixˉ+xˉ2)=xi22nxˉ+nxˉ2=xi2nxˉ
我们得到 m m m 的最终表达式:
m = ∑ ( x i − x ˉ ) ( y i − y ˉ ) ∑ ( x i − x ˉ ) 2 m = \frac{\sum (x_i - \bar{x})(y_i - \bar{y})}{\sum (x_i - \bar{x})^2} m=(xixˉ)2(xixˉ)(yiyˉ)
最后,我们使用 m m m 的值回代到 b b b 的表达式中得到 b b b b = y ˉ − m x ˉ b = \bar{y} - m\bar{x} b=yˉmxˉ这样,我们就完成了 m m m b b b 的求解过程。

3. 代码实现

根据以上思路,我们就可以写代码了。

题目描述:假设你是一位经济学家,正在研究家庭年收入(因变量 Y Y Y)与家庭主要收入者的教育年数(解释变量 X X X)之间的关系。你决定使用简单线性回归模型来分析这两个变量之间的关系。你收集了 10 个家庭的数据,如下所示:
[10, 12, 8, 15, 16, 18, 20, 14, 15, 11, 15, 19, 20]
[40, 45, 32, 50, 55, 65, 75, 48, 50, 38, 52, 70, 80]

1. 导入需要的库
import numpy as np
import matplotlib.pyplot as plt
2. 示例数据:教育年数(X)与家庭年收入(Y)的关系

——也就相当于题目给的数据集,然后题目要求我们找到他们之间的关系

X = np.array([10, 12, 8, 15, 16, 18, 20, 14, 15, 11, 15, 19, 20]).reshape(-1, 1)  # 教育年数
Y = np.array([40, 45, 32, 50, 55, 65, 75, 48, 50, 38, 52, 70, 80])  # 家庭年收入,单位:千美元
3. 绘制散点图看看数据长什么样先
# 绘制散点图
# 设置图的大小为长10,宽6
plt.figure(figsize=(8, 5), dpi=160)
plt.scatter(X, Y, color='black')
# 添加标题和坐标轴标签,中文显示会有问题,为了方便就用英文
plt.title('Education Years & Family Income')
plt.xlabel('Education Years')
plt.ylabel('Family Income')
plt.grid(True)
plt.show()

在这里插入图片描述

不使用scikit-learn库,手动实现简单线性回归,想一想如果想要用一条直线拟合这些点,我们需要计算些什么?

  • 大家应该都很了解直线,需要一个斜率,需要一个截距
  • 根据前面讲解的内容
    • 斜率的计算公式为: β 1 = ∑ i = 1 n ( X i − X ˉ ) ( Y i − Y ˉ ) ∑ i = 1 n ( X i − X ˉ ) 2 \beta_1 = \frac{\sum_{i=1}^{n}(X_i - \bar{X})(Y_i - \bar{Y})}{\sum_{i=1}^{n}(X_i - \bar{X})^2} β1=i=1n(XiXˉ)2i=1n(XiXˉ)(YiYˉ)
    • 截距的计算公式为: β 0 = Y ˉ − β 1 X ˉ \beta_0 = \bar{Y} - \beta_1\bar{X} β0=Yˉβ1Xˉ
  • 其中, X ˉ \bar{X} Xˉ Y ˉ \bar{Y} Yˉ分别为X和Y的均值
  • 有了斜率和截距,我们就可以得到回归方程: Y ^ = β 0 + β 1 X \hat{Y} = \beta_0 + \beta_1X Y^=β0+β1X
  • 有了回归方程,我们就可以预测Y值了
def simple_linear_regression(X, Y):# 计算X和Y的均值mean_X = np.mean(X)mean_Y = np.mean(Y)# 计算斜率(beta_1)和截距(beta_0)numerator = np.sum((X - mean_X) * (Y - mean_Y))denominator = np.sum((X - mean_X) ** 2)beta_1 = numerator / denominator # 斜率beta_0 = mean_Y - beta_1 * mean_X # 截距return beta_0, beta_1
4. 使用模型参数预测Y值
# 计算截距和斜率
beta_0, beta_1 = simple_linear_regression(X.flatten(), Y)# 使用模型参数预测Y值
Y_pred_manual = beta_0 + beta_1 * X
5. 绘制回归线
# 绘制数据点和手动实现的回归线
plt.figure(figsize=(8, 5), dpi=160)
plt.scatter(X, Y, color='blue', label='Actual data')
plt.plot(X, Y_pred_manual, color='green', label='Manual Regression line')
plt.xlabel('Education Years')
plt.ylabel('Family Annual Income (k$)')
plt.title('Simple Linear Regression (Manual Implementation)')
plt.legend()
plt.show()

png

print('手动实现的回归方程为:Y = {:.2f} + {:.2f}X'.format(beta_0, beta_1))
手动实现的回归方程为:Y = -1.39 + 3.72X
6. 评估模型
# 计算R^2,也就是决定系数
# R^2 = SSR/SST
# SSR:回归平方和,SST:总平方和
# R^2的取值范围是0~1,越接近1,表明模型拟合的越好
SSR = np.sum((Y_pred_manual - np.mean(Y)) ** 2)  # 回归平方和
SST = np.sum((Y - np.mean(Y)) ** 2)  # 总平方和
R_square = SSR / SST
print('手动实现的R^2 = {:.4f}'.format(R_square))
手动实现的R^2 = 0.9414

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

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

相关文章

考取ORACLE数据库OCP的必要性 Oracle数据库

OCP证书是什么? OCP,全称Oracle Certified Professional,是Oracle公司的Oracle数据库DBA(Database Administrator,数据库管理员)认证课程。这是Oracle公司针对数据库管理领域设立的一项认证课程,旨在评估和…

网盘拉新项目去哪找平台对接?推荐6个一手渠道接单!

在当今这个充满竞争的时代,网盘项目的寻找与对接成为了许多团队关注的焦点。那么,我们应该如何找到那些既靠谱又有潜力的项目呢?经过深入研究和全网检索,我为大家盘点了6个值得一试的接单渠道,助力网盘推广团队高效寻找…

matlab工具包

matlab安装yalmip和cplex出错 - 知乎 (zhihu.com) Cplex的安装和使用实例-CSDN博客 一条龙教程:Matlab下使用yalmip(工具箱)cplex(求解器)_使用yalmip和cplex求解器进行建模和求解的步骤如下:-CSDN博客 啊啊啊,好开心&#xff…

Mint_21.3 drawing-area和goocanvas的FB笔记(二)

一、goocanvas安装 Linux mint 21.3 库中带有 libgoocanvas-2.0-dev, 用sudo apt install libgoocanvas-2.0-dev 安装,安装完成后,检查一个 /usr/lib/x86_64-linux-gnu 下是否有libgoocanvas.so的软件链接。如果没有,或是 .so.x 等类似后面…

事务Transaction简写为tx的原因

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl Transaction简写的由来 数据库事务Transaction通常被简写为tx。让人疑惑的是:这个单词本身没有字母x为何又将其简写成了tx呢? 第一种可能 Transac…

“平民化”非结构数据处理

在全球信息产业高速发展的背景下,IDC预测,2018 到 2025 年之间,全球产生的数据量将会从 33 ZB 增长到 175 ZB, 复合增长率27%,其中超过 80%的数据都会是处理难度较大的非结构化数据,如文档、文本、图形、图…

javascript中的class基础入门(1)

javascript中的class start 最近在学习:cocos ,准备自己制作小游戏。过程中遇到不少疑问,我计划将这些疑问写成一个系列博客,用以记录。这篇文章来了解 class 1. 前言 1. 前言 本文对应版本 Cocos Creator 3.8。Cocos Creato…

【Sql server】假设有三个字段a,b,c 以a和b分组,如何查询a和b唯一,但是c不同的记录

欢迎来到《小5讲堂》,大家好,我是全栈小5。 这是《Sql Server》系列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对…

2_SQL

文章目录 SQL数据完整性实体完整性域完整性参照完整性default(默认值)comment(注释) 多表设计一对一一对多多对多数据库三大范式第一范式:原子性第二范式:唯一性第三范式:数据的冗余 多表查询连…

JQMobile Loader Widget 遮罩层改造

最近在用jqmobile 做一个混合APP项目时候用到 jqmobile1.4.3提供的Loader Widget控件,但是这个控件本身是一个loading弹出层,这个弹出层弹出之后,用户还是可以去点击按钮,重复发送请求,为了防止重复提交,我想了两种办法, 1,在loading弹出层弹出之后,让按钮不可用.但是form表单…

记录SSM项目集成Spring Security 4.X版本 之 加密验证和记住我功能

目录 前言 一、用户登录密码加密认证 二、记住我功能 前言 本次笔记的记录是接SSM项目集成Spring Security 4.X版本 之 加入DWZ,J-UI框架实现登录和主页菜单显示-CSDN博客https://blog.csdn.net/u011529483/article/details/136255768?spm1001.2014.3001.5502 文章之后补…

Python列表的合并、重复、判断与切片操作你学会了吗

1.合并列表 通过 实现 list1 ["佛跳墙", "肠粉", "刀削面", "烤鸭"]list2 [32, 4, 5, 7.43, True]list3 list1 list2print(list3) # [佛跳墙, 肠粉, 刀削面, 烤鸭, 32, 4, 5, 7.43, True] 2.重复输出列表中的元素 通过 * 实…

vue3 中 主题定制

vue3 中 主题定制 背景 做多主题定制,黑/白 ,里面还要再分各种颜色,每次进来都要记住上次的主题设置 效果图 一、目录结构 ├── generated │ ├── theme │ │ └── dark-yellow.ts │ │ └── dark-orange.ts │ │…

「算法」常见位运算总结

位运算符 异或 按位异或可以实现无进位相加,所谓无进位相加,就是在不考虑进位的情况下将两个数相加(后面有道题需要用到这种操作) 异或的运算律 ①a ^ 0 a ②a ^ a 0 ③a ^ b ^ c a ^ ( b ^ c ) 有符号右移>> 将一个…

IDEA切换 Springboot初始化 URL

🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 往期热门专栏回顾 专栏…

云计算 2月20号 (认识操作系统)

1、认识操作系统 计算机系统的组成 知识点1:没有软件系统的计算机称之为"裸机" 知识点2:裸机提供基本的可计算性资源 知识点3:操作系统是最靠近硬件的软件层,负责管理和控制计算机硬件。 计算机硬件组成五大部件 运算器…

代码随想录算法刷题训练营day29:LeetCode(491)递增子序列、LeetCode(46)全排列、LeetCode(47)全排列 II

代码随想录算法刷题训练营day29:LeetCode(491)递增子序列、LeetCode(46)全排列、LeetCode(47)全排列 II LeetCode(491)递增子序列 题目 代码 import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; im…

2024年AI全景预测

欢迎来到 2024 年人工智能和技术的可能性之旅。 在这里,每一个预测都是一个潜在的窗口,通向充满创新、变革、更重要的是类似于 1950 年代工业革命的未来。 20 世纪 50 年代见证了数字计算的兴起,重塑了行业和社会规范。 如今,人工…

力扣1143. 最长公共子序列(动态规划)

Problem: 1143. 最长公共子序列 文章目录 题目描述思路复杂度Code 题目描述 思路 我们统一标记:str1[i]代表text1表示的字符数组,str2[j]代表text2表示的字符数组;LCS代表最长的公共子序列;(我们易得只有str1[i]和str…

Flutter中Widget的生命周期

Widget生命周期: createState-initState-didChangeDependency-build-deactive-dispose 可通过WidgetsBinding类对widget生命周期的回调进行监控。 createState:StatefulWidget 中用于创建 State; initState:State 的初始化操作&am…