Commit on 2025/04/08 周二 12:00:24.57

This commit is contained in:
zhangsan 2025-04-08 12:00:24 +08:00
parent 18feba745b
commit 426cec0a76
8 changed files with 588 additions and 140 deletions

View File

@ -244,4 +244,76 @@ $$
**类比**:阅读时遇到关键情节,输入门打开,将新信息写入长期记忆(如角色关系),同时候选状态 $\tilde{c}_t$提供新信息的候选内容。
- **输出门 $o_t$**
控制从细胞状态中输出多少信息作为当前时间步的隐藏状态。隐藏状态 $h_t$ 通常用于后续计算(例如,生成输出、参与下一时刻计算)。
**类比**:根据当前任务(如预测下一个词),输出门决定暴露细胞状态的哪部分(如只关注时间、地点等关键信息)。
**类比**:根据当前任务(如预测下一个词),输出门决定暴露细胞状态的哪部分(如只关注时间、地点等关键信息)。
## 时序卷积网络TCN
TCN是一种专为处理序列数据设计的深度学习架构。它通过结合因果卷积、扩张卷积和残差连接解决了传统RNN和LSTM在并行化能力和梯度稳定性上的局限性。
### 1. 因果卷积Causal Convolution
因果卷积确保模型在预测时刻$t$的数据时,仅使用$t$时刻之前的信息,避免未来数据泄漏。
因果卷积类似于一个滑动窗口(窗口大小=$k$),每次用当前和过去的$k-1$个值加权求和,生成当前时刻的输出。
**公式定义**
$$
F(x_{t}) = \sum_{i=0}^{k-1} f_{i} \cdot x_{t - i}
$$
- $x_t$:时刻$t$的输入数据
- $f_i$:一维卷积核的第$i$个权重
- $k$:卷积核大小
**举例:**
1. **输入序列**$x = [x_0, x_1, x_2, x_3, x_4] = [1, 3, 2, 5, 4]$
长度为5的时间序列$x_t$表示$t$时刻的值)
2. **卷积核**$f = [f_0, f_1] = [0.5, -1]$
(大小为$k=2$,权重分别为$0.5$和$-1$
| 时刻 $t$ | 输入 $x_t$ | 计算过程 | 输出 $F(x_t)$ |
| -------- | ---------- | ---------------------------- | -------------------- |
| 0 | 1 | $0.5 \cdot 1 + (-1) \cdot 0$ | $0.5 \times 1 = 0.5$ |
| 1 | 3 | $0.5 \cdot 3 + (-1) \cdot 1$ | $1.5 - 1 = 0.5$ |
| 2 | 2 | $0.5 \cdot 2 + (-1) \cdot 3$ | $1 - 3 = -2$ |
| 3 | 5 | $0.5 \cdot 5 + (-1) \cdot 2$ | $2.5 - 2 = 0.5$ |
| 4 | 4 | $0.5 \cdot 4 + (-1) \cdot 5$ | $2 - 5 = -3$ |
**最终输出序列**
$$
F(x) = [0.5, 0.5, -2, 0.5, -3]
$$
### 2. 扩张卷积Dilated Convolution
通过**膨胀因子 $d$**在卷积核元素之间插入空洞(间隔),从而在不增加参数量的情况下**扩大感受野**。
- **传统卷积**$d=1$):连续覆盖 $k$ 个时间步(如 $x_t, x_{t-1}, x_{t-2}$)。
- **扩张卷积**$d>1$):跳跃式覆盖,跳过中间部分时间步(如 $x_t, x_{t-d}, x_{t-2d}$)。
**公式定义**
$$
F(x_{t}) = \sum_{i=0}^{k-1} f_{i} \cdot x_{t - d \cdot i}
$$
### 3. 残差连接Residual Connection
TCN借鉴ResNet通过残差块缓解梯度消失问题。
**公式定义**
$$
\text{Output} = \sigma\bigl(F(x) + W_{1\times1} x \bigr)
$$
- $F(x)$:卷积层的输出
- $\sigma$激活函数通常为ReLU
- $W_{1\times1}$1×1卷积核用于调整输入$x$的维度
- $x$:原始输入

View File

@ -868,7 +868,7 @@ $$
谱聚类的基本思想是通过图的特征向量将数据点映射到低维空间中,然后在这个低维空间中使用传统的聚类技术。
1.构造相似性图
**1.构造相似性图**
- **数据表示**
给定数据点 $\{x_1, x_2, \ldots, x_n\}$。
@ -877,9 +877,11 @@ $$
根据数据点之间的距离或相似性构造矩阵 $W$。常见方法包括:
- **Gaussian 核函数**
$$
W_{ij} = \exp\Bigl(-\frac{\|x_i - x_j\|^2}{2\sigma^2}\Bigr),
$$
只有当 $x_i$ 与 $x_j$ 彼此接近时, $W_{ij}$ 才较大;衡量数据点之间的距离并将其映射为一个 [0, 1] 之间的相似性值。
其中 $\sigma$ 为尺度参数,当 $\sigma$ 较小时,只有非常接近的数据点才会被认为是相似的
@ -888,35 +890,42 @@ $$
2.构造图拉普拉斯矩阵
**2.构造图拉普拉斯矩阵**
- 对称归一化拉普拉斯矩阵
- 未归一化的拉普拉斯矩阵
3.计算特征向量
对选定的拉普拉斯矩阵(例如 $L_{sym}$)进行特征分解,求出前 $k$ 个最小特征值对应的特征向 量。
注意:对于未归一化的拉普拉斯矩阵,零特征值对应的特征向量通常是常数向量,所以在分 解时忽略这个解,选择第二小开始的 $k$ 个特征向量。
4.构造嵌入空间
**3.计算特征向量**
对选定的拉普拉斯矩阵(例如 $L_{sym}$)进行特征分解,求出**前 $k$ 个最小特征值**对应的特征向量。
注意:对于未归一化的拉普拉斯矩阵,零特征值对应的特征向量通常是常数向量,所以在分解时忽略这个解,选择第二小开始的 $k$ 个特征向量。
**4.构造嵌入空间**
- **形成矩阵 $U$**
将求得的 $k$ 个特征向量作为列组成矩阵
将求得的 $k$ 个特征向量作为**列**组成矩阵
$$
U = \begin{pmatrix}
U = \begin{pmatrix}
u_1(1) & u_2(1) & \cdots & u_k(1) \\
u_1(2) & u_2(2) & \cdots & u_k(2) \\
\vdots & \vdots & \ddots & \vdots \\
u_1(n) & u_2(n) & \cdots & u_k(n)
\end{pmatrix}.
$$
其中,每一行对应原数据点在低维空间中的表示。
例:
- **归一化(可选)**
对于对称归一化的情况,可以对 $U$ 的每一行做归一化处理,使得每一行变为单位向量,这一步有助于后续聚类的稳定性。
5.聚类
**5.聚类**
**使用 k-means 等传统聚类算法**
在低维嵌入空间中,每一行表示一个数据点的低维表示,然后对这些点进行聚类。
@ -1102,7 +1111,7 @@ $$
1. **特征值和特征向量的定义**
对于一个对称矩阵 $A$,其特征值和特征向量满足:
$$
A x_i = \lambda_i x_i
A x_i = \lambda_i x_i
$$
其中,$\lambda_i$ 是特征值,$x_i$ 是对应的特征向量。

View File

@ -1,74 +1,43 @@
### 4.2.3 ADMM求解的变量与步骤详解
# 物理连通性约束说明
#### 1. 变量定义与作用
- **输入变量**
- $A_{pre}$:初始邻接矩阵(优化前的网络拓扑)。
- $P$对称的0-1矩阵用于标记 $A_{pre}$ 中非零元素的位置(保持已有边不变)。
- $A'_{max}$:功率最大时的邻接矩阵的补集($A'_{maxij} = 1$ 表示 $A_{maxij} = 0$,即不允许新增边)。
- $\alpha$:权衡稀疏性($L_1$ 范数)和低秩性(核范数)的系数。
- **iters**ADMM迭代次数。
## 约束目的
**禁止在物理上不可能连通的位置新增链路**,确保网络拓扑优化的合理性。
- **中间变量**
- **$D_1, D_2$**:临时变量,用于投影步骤的中间计算。
- $D_1 = A^*$来自附录A的推导可能是对偶变量或中间解
- $D_2 = R^* + A_{pre}$:结合残差 $R^*$ 和初始矩阵 $A_{pre}$ 的中间结果。
- **$M$**:残差计算的辅助矩阵,可能与约束 $A \odot P = A_{pre} \odot P$ 相关。
- **$temp\_R, temp\_A$**:内层循环的临时变量,用于梯度投影的残差计算。
- **$X, Y$**:对偶变量(拉格朗日乘子),分别对应两个约束:
- $X$:约束 $A \odot P = A_{pre} \odot P$ 的对偶变量。
- $Y$:约束 $A \odot A'_{max} = 0$ 的对偶变量。
- **$Z1, Z2$**:辅助变量,用于解耦目标函数中的核范数和 $L_1$ 范数:
- $Z1$:与核范数 $\|A\|_*$ 相关的辅助变量。
- $Z2$:与 $L_1$ 范数 $\|A\|_1$ 相关的辅助变量。
- **$U1, U2$**拉格朗日乘子用于ADMM的对偶上升步骤
- $U1$:对应 $Z1$ 的约束 $A = Z1$。
- $U2$:对应 $Z2$ 的约束 $A = Z2$。
## 矩阵定义
---
1. **最大功率连通矩阵** $A_{\max}$:
- 表示节点在最大发射功率下的连通性
- 非零元素:$A_{\max,ij} \neq 0$ 表示可连通
- 零元素:$A_{\max,ij} = 0$ 表示即使满功率也无法连通
#### 2. 算法步骤详解
##### (S.1) 更新原始变量 $A$ADMM的 $x$ 步)
通过内层循环(投影和对偶上升)更新 $A$,确保其满足两个约束:
1. **投影到 $A \odot P = A_{pre} \odot P$**(保持已有边不变):
- **行4-11**:梯度投影法迭代更新 $R$(残差)。
- $temp\_R^{k+1} = M - X^k \odot A_{pre}$:计算当前残差($M$ 可能是约束的右端项)。
- $X^{k+1} = X^k + \beta (A_{pre} \odot temp\_R^{k+1})$:对偶变量 $X$ 的梯度上升(步长 $\beta$)。
- **本质**:通过迭代强制 $A$ 在 $P$ 标记的位置与 $A_{pre}$ 一致。
2. **互补矩阵** $A'_{\max}$:
$$
A'_{\max,ij} =
\begin{cases}
0, & A_{\max,ij} \neq 0 \\
1, & A_{\max,ij} = 0
\end{cases}
$$
- 在物理不可连通位置为1其他位置为0
2. **投影到 $A \odot A'_{max} = 0$**(禁止新增边):
- **行13-17**:类似地,更新 $Y$
- $temp\_A^{k+1} = D_2 - Y^k \odot A'_{max}$:残差计算。
- $Y^{k+1} = Y^k + \gamma (A'_{max} \odot temp\_A^{k+1})$:对偶变量 $Y$ 的更新(步长 $\gamma$)。
## 约束条件
$$
A \odot A'_{\max} = 0
$$
##### (S.2) 更新辅助变量 $Z1, Z2$ADMM的 $z$ 步)
通过阈值操作分离目标函数的两部分:
1. **$Z1^{t+1} = T_r(A^{t+1} + U1^t)$**
- $T_r(\cdot)$:奇异值阈值算子(核范数投影)。
- 对 $A + U1$ 做SVD分解保留前 $r$ 个奇异值($r$ 由低秩性需求决定)。
- **作用**:强制 $A$ 低秩。
**解释**
- $\odot$ 表示Hadamard积逐元素相乘
- 约束强制要求:对于所有满足 $A'_{\max,ij}=1$ 的位置(即物理不可连通的节点对),必须有 $A_{ij}=0$
2. **$Z2^{t+1} = S_{\alpha}(A^{t+1} + U2^t)$**
- $S_{\alpha}(\cdot)$:软阈值算子($L_1$ 范数投影)。
- 对 $A + U2$ 的每个元素:$\text{sign}(x) \cdot \max(|x| - \alpha, 0)$。
- **作用**:促进 $A$ 的稀疏性。
## 实际效果
##### (S.3) 更新拉格朗日乘子 $U1, U2$ADMM的对偶上升
通过残差调整乘子:
- $U1^{t+1} = U1^t + A^{t+1} - Z1^{t+1}$:核范数约束的乘子更新。
- $U2^{t+1} = U2^t + A^{t+1} - Z2^{t+1}$$L_1$ 范数约束的乘子更新。
- **作用**:惩罚 $A$ 与辅助变量 $Z1, Z2$ 的偏差,推动收敛。
1. **可调连接**
- 原本能连通的节点对($A_{\max,ij} \neq 0$)可以根据优化目标自由调整
---
2. **固定断开**
- 物理上无法连通的节点对($A_{\max,ij} = 0$)始终保持断开($A_{ij} = 0$
#### 3. 关键点总结
1. **投影步骤**:内层循环通过梯度法将 $A$ 投影到两个约束集合(保持已有边 + 禁止新增边)。
2. **变量解耦**$Z1, Z2$ 分离低秩和稀疏目标ADMM通过交替更新协调二者。
3. **凸性保证**:核范数和 $L_1$ 范数均为凸函数ADMM能收敛到全局最优解。
4. **并行性**每个节点可独立运行算法行1注释适合分布式网络优化。
---
#### 可能的疑问与验证
- **$M$ 的具体定义**:文中未明确,可能是 $A_{pre} \odot P$ 或其他约束右端项。
- **$D_1, D_2$ 的推导**需参考附录A的公式4-334-40可能涉及对偶问题的转换。
- **步长 $\beta, \gamma$**:通常需手动调参或通过线搜索确定。
## 应用意义
- 保证网络拓扑优化不违反物理层连接限制
- 避免算法建议不切实际的通信链路
- 维持网络部署的可行性

View File

@ -719,8 +719,6 @@ $V$ 和 $H$ 是 $r \times r$。
$\mathcal{O}(r^3)$
(3) 由于通常 $n \gg r$$\mathcal{O}(n r^2)$ 是主导项,故总复杂度(其中 $T$ 为迭代次数)
$$
T \cdot \mathcal{O}(nr^2)

View File

@ -1,6 +1,32 @@
## 颜佳佳论文
# 颜佳佳论文
### 网络结构优化
## 多智能体随机网络结构的实时精确估算
### 基于扰动理论的特征向量估算方法
**计算特征值扰动**
$$\Delta \lambda_{A_i} = \lambda_{A2} - \lambda_{A1}$$
**特征向量修正项**
$$
U_B = \sum_{k=1}^{n} \frac{\Delta \lambda_{A_i} U_k}{(\lambda_{A_i} - \lambda_{A_k})}
$$
- **解释**
- $U_k$ 是 $A_{t1}$ 的第 $k$ 个特征向量
- 分母 $(\lambda_{A_i} - \lambda_{A_k})$ 表示特征值差异,避免奇异(需假设 $\lambda_{A_i} \neq \lambda_{A_k}$
- 分子 $\Delta \lambda_{A_i}$ 反映特征值变化对特征向量的影响
**更新特征向量**
$$
U_{A2} = U_{A1} + U_B
$$
**意义**:通过一阶扰动修正当前特征向量,得到未来时刻的 $U_{A2}$
## 网络结构优化
**直接SNMF分解无优化**
@ -23,7 +49,7 @@
#### 网络优化中的邻接矩阵重构问题建模与优化
### 网络优化中的邻接矩阵重构问题建模与优化
**可行解集合定义公式4-4**
$$
@ -31,7 +57,7 @@ $$
$$
- **$A^T = A$**:确保邻接矩阵对称
- **$A \odot P = A_{\text{pre}} \odot P$**:掩码矩阵$P$ 指定位置的原始值$\odot$为Hadamard积
- **$A \odot P = A_{\text{pre}} \odot P$**:掩码矩阵$P$ **原来已有的连接不变,只让优化原本没有连接的地方**。$\odot$为Hadamard积
- **$A \odot A_{\max}' = 0$**:功率约束矩阵$\ A_{\max}'$ 禁止在原本无连接的节点间新增边
@ -45,7 +71,9 @@ A'_{\max, ij} =
\end{cases}
$$
- 通过$A_{\max}'$​标记禁止修改的零元素位置
- $A_{\max, ij}$表示在最大发射功率下哪些节点对之间能连通(非零表示可连通,零表示即便满功率也连不通)
- $A_{\max}'$在“连不通”的位置上是1其他位置是0。通过$A_{\max}'$标记禁止修改的零元素位置
- 对于所有满足 $A'_{\max,ij}=1$ 的位置(即物理不可连通的节点对),必须有 $A_{ij}=0$,即始终保持断开
@ -80,9 +108,9 @@ $$
#### ADMM核心算法
### ADMM核心算法
##### **变量定义与作用**
#### **变量定义与作用**
- **输入变量**
- $A_{pre}$:初始邻接矩阵(优化前的网络拓扑)。
@ -97,12 +125,12 @@ $$
##### **算法步骤详解**
#### **算法步骤详解**
**(S.1) 更新原始变量 $A$对应ADMM的$x$步)**
- **代码行4-17**:通过内层循环(投影和对偶上升)更新 $A$。
- **行4-11**将 $A$ 投影到约束 $A \odot P = A_{\text{pre}} \odot P$ 的集合。
- **行4-11**
- 通过内层循环行8-11迭代更新 $R$,本质是**梯度投影法**
- $temp_R^{k+1} = M - X^k \odot A_{\text{pre}}$(计算残差)。
- $X^{k+1} = X^k + \beta(A_{\text{pre}} \odot temp_R^{k+1})$(梯度上升步,$\beta$ 为步长)。
@ -128,3 +156,162 @@ $$
- $U_1^{t+1} = U_1^t + A^{t+1} - Z_1^{t+1}$(核范数约束的乘子更新)。
- $U_2^{t+1} = U_2^t + A^{t+1} - Z_2^{t+1}$$L_1$ 范数约束的乘子更新)。
- **作用**:惩罚 $A$ 与辅助变量 $Z1, Z2$ 的偏差(迫使$A$更贴近$Z$),推动收敛。
## 网络结构控制
- **核心目标**:将优化后的低秩稀疏矩阵 $A$ 转化为**实际网络参数**(如功率、带宽),并维持动态网络的**连通性**和**稳定性**。
- **具体实现**
1. 通过PID控制调整发射/接收功率,使实际链路带宽匹配矩阵 $A$ 的优化值。
2. 结合CSMA/CA协议处理多节点竞争确保稀疏网络下的高效通信。
```plaintext
优化模型4.2节)
↓ 生成目标带宽矩阵A
香农公式 → 计算目标Pr → 自由空间公式 → 计算目标Pt
PID控制发射机AGC电压 → 实际Pt ≈ 目标Pt
PID控制接收机AAGC/DAGC → 实际Pr ≈ 目标Pr
实际带宽 ≈ Aij (闭环反馈)
```
- **发射机**
- **功能**:将数据转换为无线信号并通过天线发射。
- **关键参数**:发射功率($P_t$)、天线增益($G_t$)、工作频率(决定波长$\lambda$)。
- **控制目标**通过调整AGC电压动态调节发射功率以匹配优化后的带宽需求矩阵$A$中的$A_{ij}$)。
- **接收机**
- **功能**:接收无线信号并转换为可处理的数据。
- **关键参数**:接收功率($P_r$)、噪声($N_0$)、天线增益($G_r$)。
- **控制目标**通过AAGC/DAGC增益调整确保接收信号强度适合解调维持链路稳定性。
### 具体步骤
**步骤1生成目标带宽矩阵 $A$4.2节优化模型)**
- **数学建模**
- 通过凸松弛优化问题公式4-7得到低秩稀疏矩阵 $A$
$$
\min_A (1-\alpha) \|A\|_* + \alpha \|A\|_1 \quad \text{s.t.} \quad A \in \Omega
$$
- 约束集 $\Omega$ 确保矩阵对称性、保留原有链路($A \odot P = A_{\text{pre}} \odot P$)、禁止不可达链路($A \odot A'_{\max} = 0$)。
- **物理意义**
- 非零元素 $A_{ij}$ 直接表示 **目标信道带宽** $C_{ij}$单位bps
$$
A_{ij} = C_{ij} = W \log_2\left(1 + \frac{P_r}{N_0 W}\right) \quad \text{(香农公式4-10)}
$$
**步骤2从带宽 $A_{ij}$ 反推功率参数**
- **接收功率 $P_r$ 计算**
- 根据香农公式解耦:
$$
P_r = (2^{A_{ij}/W} - 1) N_0 W
$$
- **输入**:噪声 $N_0$、带宽 $W$、目标带宽 $A_{ij}$。
- **发射功率 $P_t$ 计算**
- 通过自由空间公式4-11
$$
P_t = \frac{P_r L (4\pi d)^2}{G_t G_r \lambda^2}
$$
- **输入**:距离 $d$、天线增益 $G_t, G_r$、波长 $\lambda$、损耗 $L$。
- **逻辑分支**
- 若 $A_{ij} \neq A_{\text{pre}ij}$(需调整链路):
- 计算 $P_r$ 和 $P_t$
- 若 $A_{ij} = 0$(无连接):
- 直接设 $P_r = P_t = 0$。
**步骤3发射机功率调整图4-2a**
1. **定义目标**$P_t$来自步骤2
2. **测量实际**:通过传感器获取当前发射功率 $P_{t,\text{actual}}$。
3. **计算偏差**$e(t) = P_t - P_{t,\text{actual}}$。
4. **PID调节**通过AGC电压改变发射功率逼近 $P_t$。
**步骤4接收机功率调整图4-2b**
1. **定义目标**$P_r$来自步骤2
2. **测量实际**:检测空口信号功率 $P_{r,\text{actual}}$。
3. **计算偏差**$e(t) = P_r - P_{r,\text{actual}}$。
4. **PID调节**
- 调整AAGC模拟增益和DAGC数字增益持续监测直至 $|e(t)| < \epsilon$。
## 智能体随机网络结构实时表示的应用
### (1) 谱聚类分组Spectral_Clustering表5.1
**目标**:将无人机和充电站划分为 $K$ 个簇,使充电站位于簇中心。
**步骤**
1. **输入**:带权邻接矩阵 $A$(权值=无人机间距离)、节点数 $N$、充电站数 $K$。
2. **拉普拉斯矩阵**
$$L = D - A, \quad D_{ii} = \sum_j A_{ij}$$
3. **归一化**
$$L_{norm} = D^{-\frac{1}{2}}LD^{\frac{1}{2}}$$
4. **谱分解**:求 $L_{norm}$ 前 $K$ 小特征值对应的特征向量矩阵 $V \in \mathbb{R}^{N \times K}$。
5. **聚类**:对 $V$ 的行向量进行 k-means 聚类,得到标签 $\text{labels}$。
**输出**:每个无人机/充电站的簇编号 $\text{labels}$。
### (2) 无人机选择充电站表5-2
**目标**:电量低的无人机前往对应簇中心的充电站。
**步骤**
1. **周期性运行**(间隔 $\Delta t$
- 通过 `Push_Sum` 协议获取所有无人机位置 `Positions`
- 计算距离矩阵 $A$。
2. **动态聚类**:调用 `Spectral_Clustering(A)` 更新簇标签。
3. **充电触发**:若电量 $E < P_{th}$向簇中心请求坐标 $\text{CS\_point}$ 并前往
**关键公式**
$$A_{ij} = \| \text{Position}_i - \text{Position}_j \|_2$$
### (3) 充电站跟踪算法表5-3
**目标**:充电站动态调整位置至簇中心。
**步骤**
1. **周期性运行**(间隔 $\Delta t$
- 同无人机算法获取 $A$ 和 `labels`
2. **定位簇中心**
- 充电站根据编号匹配簇标签。
- 计算簇内无人机位置均值:
$$\text{CS\_point} = \frac{1}{|C_k|} \sum_{i \in C_k} \text{Position}_i$$
其中 $C_k$ 为第 $k$ 簇的节点集合。
3. **移动至新中心**并广播位置。
---
### (4) 算法改进
**替换通信协议**用第3章的卡尔曼滤波 替代 `Push_Sum`,获取特征值、特征向量重构全局矩阵 $A$,减少消息传递。

View File

@ -156,6 +156,51 @@ IDEA快捷键
5. switch-case
```java
public class SwitchCaseExample {
public static void main(String[] args) {
// 定义一个 int 类型变量,作为 switch 的表达式
int day = 3;
String dayName;
// 根据 day 的值执行相应的分支
switch(day) {
case 1:
dayName = "Monday"; // 当 day 为 1 时
break; // 结束当前 case
case 2:
dayName = "Tuesday"; // 当 day 为 2 时
break;
case 3:
dayName = "Wednesday"; // 当 day 为 3 时
break;
case 4:
dayName = "Thursday"; // 当 day 为 4 时
break;
case 5:
dayName = "Friday"; // 当 day 为 5 时
break;
case 6:
dayName = "Saturday"; // 当 day 为 6 时
break;
case 7:
dayName = "Sunday"; // 当 day 为 7 时
break;
default:
// 如果 day 不在 1 到 7 之间
dayName = "Invalid day";
}
// 输出最终结果
System.out.println("The day is: " + dayName);
}
}
```
#### Java传参方式

View File

@ -351,49 +351,154 @@ public class PriorityQueueExample {
**自己实现大根堆:**
**自定义排序:按第二个元素的值构建小根堆**
如何比较器返回负数,则第一个数排在前面->优先级高->在堆顶
```java
class Solution {
public int findKthLargest(int[] nums, int k) {
int heapSize = nums.length;
buildMaxHeap(nums, heapSize);
for (int i = nums.length - 1; i >= nums.length - k + 1; --i) {
swap(nums, 0, i);
--heapSize;
maxHeapify(nums, 0, heapSize);
public class CustomPriorityQueue {
public static void main(String[] args) {
// 定义一个 PriorityQueue其中每个元素是 int[],并且按照数组第二个元素升序排列
PriorityQueue<int[]> minHeap = new PriorityQueue<>(
(a, b) -> return a[i]-b[i];
);
// 添加数组
minHeap.offer(new int[]{1, 2});
minHeap.offer(new int[]{3, 4});
minHeap.offer(new int[]{0, 5});
// 依次取出元素,输出结果
while (!minHeap.isEmpty()) {
int[] arr = minHeap.poll();
System.out.println(Arrays.toString(arr));
}
return nums[0];
}
}
```
不用lambda版本
```java
PriorityQueue<int[]> minHeap = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] a, int[] b) {
return a[1] - b[1];
}
});
```
##### **自己实现小根堆:**
**父节点**:对于任意索引 `i`,其父节点的索引为 `(i - 1) // 2`
**左子节点**:索引为 `i` 的节点,其左子节点的索引为 `2 * i + 1`
**右子节点**:索引为 `i` 的节点,其右子节点的索引为 `2 * i + 2`
**上滤与下滤操作**
- **上滤**Sift-Up
用于插入操作。将新加入的元素与其父节点不断比较,若小于父节点则交换,直到满足堆序性质。
- **下滤**Sift-Down
用于删除操作或建堆。将根节点或某个节点与其子节点中较小的进行比较,若大于子节点则交换,直至满足堆序性质。
**建堆:**从数组中最后一个非叶节点开始(索引为 `heapSize/2 - 1`),对每个节点执行**下滤**操作sift-down
**插入元素:**将新元素插入到堆的末尾,然后执行**上滤**操作sift-up以保持堆序性质。
**弹出元素(删除堆顶):**弹出操作一般是删除堆顶元素(小根堆中即最小值),然后用堆尾元素替代堆顶,再进行**下滤**操作。
```java
class MinHeap {
private int[] heap; // 数组存储堆元素
private int size; // 当前堆中元素的个数
// 构造函数初始化堆capacity为堆的最大容量
public MinHeap(int capacity) {
heap = new int[capacity];
size = 0;
}
public void buildMaxHeap(int[] a, int heapSize) {
// 插入元素:先将新元素添加到数组末尾,然后执行上滤操作恢复堆序性质
public void insert(int value) {
if (size >= heap.length) {
throw new RuntimeException("Heap is full");
}
// 将新元素放到末尾
heap[size] = value;
int i = size;
size++;
// 上滤操作:不断与父节点比较,若新元素小于父节点则交换
while (i > 0) {
int parent = (i - 1) / 2;
if (heap[i] < heap[parent]) {
swap(heap, i, parent);
i = parent;
} else {
break;
}
}
}
// 弹出堆顶元素:移除堆顶(最小值),用最后一个元素替换堆顶,然后下滤恢复堆序
public int pop() {
if (size == 0) {
throw new RuntimeException("Heap is empty");
}
int min = heap[0];
// 将最后一个元素移到堆顶
heap[0] = heap[size - 1];
size--;
// 对新的堆顶执行下滤操作,恢复堆序性质
minHeapify(heap, 0, size);
return min;
}
// 建堆将无序数组a构造成小根堆heapSize为数组长度
public static void buildMinHeap(int[] a, int heapSize) {
for (int i = heapSize / 2 - 1; i >= 0; --i) {
maxHeapify(a, i, heapSize);
}
}
public void maxHeapify(int[] a, int i, int heapSize) {
int l = i * 2 + 1, r = i * 2 + 2, largest = i;
if (l < heapSize && a[l] > a[largest]) {
largest = l;
}
if (r < heapSize && a[r] > a[largest]) {
largest = r;
}
if (largest != i) {
swap(a, i, largest);
maxHeapify(a, largest, heapSize);
minHeapify(a, i, heapSize);
}
}
public void swap(int[] a, int i, int j) {
// 下滤操作从索引i开始将子树调整为小根堆
public static void minHeapify(int[] a, int i, int heapSize) {
int l = 2 * i + 1, r = 2 * i + 2;
int smallest = i;
// 判断左子节点是否存在且比当前节点小
if (l < heapSize && a[l] < a[smallest]) {
smallest = l;
}
// 判断右子节点是否存在且比当前最小节点小
if (r < heapSize && a[r] < a[smallest]) {
smallest = r;
}
// 如果最小值不是当前节点,交换后继续对被交换的子节点执行下滤操作
if (smallest != i) {
swap(a, i, smallest);
minHeapify(a, smallest, heapSize);
}
}
// 交换数组中两个位置的元素
public static void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
```
改为大根堆只需要把里面 ''<'' 符号改为 ''>''
#### **`ArrayList`**
@ -571,7 +676,14 @@ public class ArrayExample {
```
int[] source = {1, 2, 3, 4, 5};
int[] destination = Arrays.copyOf(source, source.length);
int[] partialArray = Arrays.copyOfRange(source, 1, 4); //不包括索引4
int[] partialArray = Arrays.copyOfRange(source, 1, 4); //复制指定元素不包括索引4
```
初始化:
```
int[] memo = new int[nums.length];
Arrays.fill(memo, -1);
```
@ -1348,3 +1460,39 @@ public class Permute {
}
```
#### 大小根堆
**题目描述**:给定一个整数数组 `nums` 和一个整数 `k`,返回出现频率最高的前 `k` 个元素,返回顺序可以任意。
**解法一:大根堆(最大堆)**
**思路**
1. 使用 `HashMap` 统计每个元素的出现频率。
2. 构建一个**大根堆**`PriorityQueue` + 自定义比较器),根据频率降序排列。
3. 将所有元素加入堆中,**弹出前 `k` 个元素**即为答案。
**适合场景**
- 实现简单,适用于对全部元素排序后取前 `k` 个。
- 时间复杂度:**O(n log n)**,因为需要将所有 `n` 个元素都加入堆。
------
**解法二:小根堆(最小堆)**
**思路**
1. 使用 `HashMap` 统计频率。
2. 构建一个**小根堆**,堆中仅保存前 `k` 个高频元素。
3. 遍历每个元素:
- 如果堆未满,直接加入。
- 如果当前元素频率大于堆顶(最小频率),则弹出堆顶,加入当前元素。
4. 最终堆中保存的就是前 `k` 个高频元素。
| 方法 | 适合场景 | 时间复杂度 | 空间复杂度 |
| ------ | --------------- | ---------- | ---------- |
| 大根堆 | k ≈ n简单易写 | O(n log n) | O(n) |
| 小根堆 | k ≪ n更高效 | O(n log k) | O(n) |

View File

@ -1,33 +1,53 @@
ConcurrentHashMap 不同JDK版本的实现对比
- 当然可以!下面是你可以直接记到笔记里的内容:
1. 数据结构
------
- **JDK1.7**
- 使用 `Segment分段锁 + HashEntry数组 + 链表` 的数据结构
- **JDK1.8及之后**
- 使用 `数组 + 链表/红黑树` 的数据结构与HashMap类似
### 🧠 题型:**Top K 高频元素**LeetCode 347
2. 锁的类型与宽度
**题目描述**:给定一个整数数组 `nums` 和一个整数 `k`,返回出现频率最高的前 `k` 个元素,返回顺序可以任意。
- **JDK1.7**
- 分段锁(Segment)继承了 `ReentrantLock`
- Segment容量默认16不会扩容 → 默认支持16个线程并发访问
------
- **JDK1.8**
- 使用 `synchronized + CAS` 保证线程安全
- 空节点通过CAS添加
- 非空节点通过synchronized加锁
### 📌 解法一:大根堆(最大堆)
3. 渐进式扩容JDK1.8+
**思路**
- **触发条件**:元素数量 ≥ `数组容量 × 负载因子(默认0.75)`
- **扩容过程**
1. 创建2倍大小的新数组
2. 线程操作数据时,逐步迁移旧数组数据到新数组
3. 使用 `transferIndex` 标记迁移进度
4. 直到旧数组数据完全迁移完成
1. 使用 `HashMap` 统计每个元素的出现频率。
2. 构建一个**大根堆**`PriorityQueue` + 自定义比较器),根据频率降序排列。
3. 将所有元素加入堆中,**弹出前 `k` 个元素**即为答案。
### 关键改进点:
- 降低大数据量扩容时的性能开销
- 允许读写操作与扩容并发进行
**适合场景**
- 实现简单,适用于对全部元素排序后取前 `k` 个。
- 时间复杂度:**O(n log n)**,因为需要将所有 `n` 个元素都加入堆。
------
### 📌 解法二:小根堆(最小堆)
**思路**
1. 使用 `HashMap` 统计频率。
2. 构建一个**小根堆**,堆中仅保存前 `k` 个高频元素。
3. 遍历每个元素:
- 如果堆未满,直接加入。
- 如果当前元素频率大于堆顶(最小频率),则弹出堆顶,加入当前元素。
4. 最终堆中保存的就是前 `k` 个高频元素。
**适合场景**
- 当 `k ≪ n` 时效率更高。
- 时间复杂度:**O(n log k)**,因为堆中最多维护 `k` 个元素。
------
### ✅ 总结对比:
| 方法 | 适合场景 | 时间复杂度 | 空间复杂度 |
| ------ | --------------- | ---------- | ---------- |
| 大根堆 | k ≈ n简单易写 | O(n log n) | O(n) |
| 小根堆 | k ≪ n更高效 | O(n log k) | O(n) |
------
需要我再写成代码模板笔记也可以,随时说!