今日总结
- java随笔录——什么是聚簇索引,什么是非聚簇索引?什么是覆盖索引?
- AI随探录——NLP中RNN到Attention机制的演进
- 代码随想录——n皇后,贪心算法—分发饼干
目录
今日总结
详细内容
java随笔录
1、什么是聚簇索引,什么是非聚簇索引?
2、什么是覆盖索引?
AI随探录
NLP中RNN到Attention机制的演进
代码随想录
回溯算法—n皇后
贪心算法——分发饼干
详细内容
java随笔录
1、什么是聚簇索引,什么是非聚簇索引?
- 如果存在主键,主键索引就是聚集索引
- 如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引
- 如果表没有主键或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引
2、什么是覆盖索引?
- select * from user where id = 2;
- select id,name from user where name = 'liliya';
- select id, name ,gender from user where name = 'liliya';
AI随探录
NLP中RNN到Attention机制的演进
1、循环神经网络RNN
通过隐藏状态传递历史信息,(h_t = tanh(W_{ih} * x_t + W_{hh} * h_{t-1} + b_h)),其中(h_{t-1})是上一时刻的隐藏状态,负责传递历史信息;tanh是激活函数,限制输出范围(-1~1)。仅通过一个循环单元实现时序依赖建模。
但是对于早期时刻的信息难以捕捉,会造成梯度消失或梯度爆炸问题。
通过隐藏状态传递历史信息,(h_t = tanh(W_{ih} * x_t + W_{hh} * h_{t-1} + b_h)),其中(h_{t-1})是上一时刻的隐藏状态,负责传递历史信息;tanh是激活函数,限制输出范围(-1~1)。仅通过一个循环单元实现时序依赖建模。
但是对于早期时刻的信息难以捕捉,会造成梯度消失或梯度爆炸问题。
2、长短期记忆网络(LSTM)
针对 RNN 的 “梯度消失” 和 “长记忆缺失” 问题,提出结构化记忆单元,通过三大门控机制(遗忘门、输入门、输出门)精确控制信息的存储更新遗忘。解决了长依赖问题,但是参数数量暴增,训练成本变高,结构变得很复杂。
3、门控循环单元(GRU)
在 LSTM 的基础上简化结构,保留核心门控逻辑,同时减少参数和计算量,将遗忘门和输入门合并为更新门,用重置门替代输出门。
4、Seq2Seq(Encoder-Decoder)模型
编码器主要由一个循环神经网络(RNN/LSTM/GRU)构成,其任务是将输入序列的语义信息提取并压缩为一个上下文向量。
在模型处理输入序列时,循环神经网络会依次接收每个token的输入,并在每个时间步步更新隐藏状态。每个隐藏状态都携带了截止到当前位置为止的信息。随着序列推进,信息不断累积,最终会在最后一个时间步形成一个包含整句信息的隐藏状态。
这个最后的隐藏状态就会作为上下文向量(context vector),传递给解码器,用于指导后续的序列生成。
解码器主要也由一个循环神经网络(RNN / LSTM / GRU)构成,其任务是基于编码器传递的上下文向量,逐步生成目标序列。
在生成开始时,循环神经网络以上下文向量作为初始隐藏状态,并接收一个特殊的起始标记 <sos>(start of sentence)作为第一个时间步的输入,用于预测第一个 token。
随后,在每一个时间步,模型都会根据前一时刻的隐藏状态和上一步生成的 token,预测当前的输出。这种“将前一步的输出作为下一步输入”的方式被称为自回归生成(Autoregressive Generation),它确保了生成结果的连贯性。
生成过程会持续进行,直到模型生成了一个特殊的结束标记 <eos>(end of sentence),表示句子生成完成。
说明:起始标记和结束标记会在训练数据中显式添加,模型会在训练中学会何时开始、如何续写,以及何时结束,从而掌握完整的生成流程。
5、Attention 机制
传统的 Seq2Seq 模型中,编码器在处理源句时,无论其长度如何,最终都只能将整句信息压缩为一个固定长度的上下文向量,用作解码器的唯一参考。这种设计存在两个显著问题:
- 信息压缩困难:固定向量难以完整表达长句或复杂语义,容易丢失关键信息;
- 缺乏动态感知:解码器在每一步生成中都只能依赖同一个上下文向量,难以根据不同位置的生成需要灵活提取信息。
为了解决上述问题,研究者引入了 Attention 机制。其核心思想是:
解码器在生成目标序列的每一步时,不再依赖于一个静态的上下文向量,而是根据当前的解码状态,动态地从编码器各时间步的隐藏状态中选取最相关的信息,以辅助当前步的生成。
代码随想录
回溯算法—n皇后
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题研究的是如何将
n个皇后放置在n×n的棋盘上,并且使皇后彼此之间不能相互攻击。给你一个整数
n,返回所有不同的n皇后问题的解决方案。每一种解法包含一个不同的n 皇后问题的棋子放置方案,该方案中
'Q'和'.'分别代表了皇后和空位。示例 1:
输入:n = 4输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]解释:如上图所示,4 皇后问题存在两个不同的解法。示例 2:
输入:n = 1输出:[["Q"]]
class Solution { List<List<String>> result = new ArrayList<>(); private void back(int n, int row,char[][] chessboard) { if(row == n) { result.add(ArraytoList(chessboard)); return; } for(int i = 0; i < n; i++) { if(isValue(row,i,n,chessboard)) { chessboard[row][i] = 'Q'; back(n,row + 1, chessboard); chessboard[row][i] = '.'; } } } public List ArraytoList(char[][] chessboard) { List<String> list = new ArrayList<>(); for (char[] c : chessboard) { list.add(String.copyValueOf(c)); } return list; } public boolean isValue(int row,int col, int n, char[][] chessboard ) { for (int i=0; i<row; ++i) { if (chessboard[i][col] == 'Q') { return false; } } for (int i=row-1, j=col-1; i>=0 && j>=0; i--, j--) { if (chessboard[i][j] == 'Q') { return false; } } for (int i=row-1, j=col+1; i>=0 && j<=n-1; i--, j++) { if (chessboard[i][j] == 'Q') { return false; } } return true; } public List<List<String>> solveNQueens(int n) { char[][] chessboard = new char[n][n]; for (char[] c : chessboard) { Arrays.fill(c, '.'); } back(n, 0, chessboard); return result; } }贪心算法——分发饼干
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子
i,都有一个胃口值g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干j,都有一个尺寸s[j]。如果s[j] >= g[i],我们可以将这个饼干j分配给孩子i,这个孩子会得到满足。你的目标是满足尽可能多的孩子,并输出这个最大数值。示例 1:
输入:g = [1,2,3], s = [1,1]输出:1解释:你有三个孩子和两块小饼干,3 个孩子的胃口值分别是:1,2,3。 虽然你有两块小饼干,由于他们的尺寸都是 1,你只能让胃口值是 1 的孩子满足。 所以你应该输出 1。示例 2:
输入:g = [1,2], s = [1,2,3]输出:2解释:你有两个孩子和三块小饼干,2 个孩子的胃口值分别是 1,2。 你拥有的饼干数量和尺寸都足以让所有孩子满足。 所以你应该输出 2。
class Solution { public int findContentChildren(int[] g, int[] s) { reverse(g); reverse(s); int sum = 0; for(int i = 0, j = 0; i < g.length && j < s.length;) { if(s[j] >= g[i]) { j++; sum++; } i++; } return sum; } void reverse(int[] arr) { Arrays.sort(arr); for (int i = 0; i < arr.length / 2; i++) { int temp = arr[i]; arr[i] = arr[arr.length - 1 - i]; arr[arr.length - 1 - i] = temp; } } }