8.25 dfs|神经网络|math

lc82

引入flag,标记重复_跳过

return前处理:newhead->next=nullptr; //截断尾部可能的残留

class Solution {

public:

ListNode* deleteDuplicates(ListNode* head)

{

if(!head || !head->next)

return head;

ListNode* newhead=new ListNode(0);

ListNode* ret=newhead;

int flag=-1000;

while(head)

{

if(head->next && head->val==head->next->val)

flag=head->val;

++if(head->val!=flag)++

{

newhead->next=head;

newhead=newhead->next;

}

head=head->next;

}

++newhead->next=nullptr; //截断尾部可能的残留++

return ret->next;

}

};

lc52

dfs 尝试逐行处理

class Solution {

vector<bool> cols,diag1,diag2;

int n=0,ret=0;

public:

int totalNQueens(int n)

{

this->n=n;

cols.resize(n,false);

diag1.resize(n+n,false);

diag2.resize(n+n,false);

dfs(0);

return ret;

}

void dfs(int j)

{

if(j==n)

{

ret++;

return;

}

for(int i=0;i<n;i++)

{

if(!cols[i] && !diag1[i+j] && !diag2[i-j+n])

{

cols[i]=diag1[i+j]=diag2[i-j+n]=true;

dfs(j+1);

cols[i]=diag1[i+j]=diag2[i-j+n]=false;

}

}

}

};

lc1652

拼接2*n数组之后,前缀和

class Solution {

public:

vector<int> decrypt(vector<int>& code, int k) {

int n=code.size();

vector<int> t=code;

t.insert(t.end(),code.begin(),code.end());

vector<int> pre(2*n);

pre[0]=code[0];

for(int i=1;i<2*n;i++)

{

pre[i]=pre[i-1]+t[i];

}

for(int i=0;i<n;i++)

{

if(k>=0)

code[i]=pre[i+k]-pre[i];

else

code[i]=pre[i+n-1]-pre[i+n+k-1];

}

return code;

}

};

lc1089 复写0

双指针

预统计,找到右端点+反向填充

class Solution {

public:

void duplicateZeros(vector<int>& arr) {

int n = arr.size(), i, j = n-1, k = n-1;

for(i = 0; i < j; ++i)

if(arr[i] == 0)

--j;

// 此处特判需要多加思考

if(i == j && arr[i] == 0) arr[k--] = arr[j--];

while(j >= 0)

{

if(arr[j] == 0)

arr[k--] = 0;

arr[k--] = arr[j--];

}

}

};

lc498

按对角线(行&列 和相同)分组矩阵元素

偶数索引对角线reverse

依次拼接所有元素,得到对角线遍历结果。

class Solution {

public:

vector<int> findDiagonalOrder(vector<vector<int>>& mat)

{

int m=mat.size(),n=mat[0].size();

vector<vector<int>> diag(m+n-1);

for(int i=0;i<m;i++)

{

for(int j=0;j<n;j++)

{

//对角线 和等

diag[i+j].push_back(mat[i][j]);

}

}

int i=0;

vector<int> ret;

for(auto& d:diag)

{

if(i%2==0)

//偶数列 从下往上

reverse(d.begin(),d.end());

i++;

for(auto& a:d)

ret.push_back(a);

}

return ret;

}

};

lc2316

int DFS找出图中所有连通块的大小

然后计算不同连通块之间的节点对数量总和(乘法原理)

class Solution {

public:

long long countPairs(int n, vector<vector<int>> &edges) {

vector<vector<int>> g(n);

for (auto &e: edges) {

int x = e[0], y = e[1];

g[x].push_back(y);

g[y].push_back(x); // 建图

}

vector<int> vis(n);

function<int(int)> dfs = [&](int x) -> int

{

vis[x] = true; // 避免重复访问同一个点

++int size = 1;
for (int y: g[x]) {
if (!vis[y]) {
size += dfs(y);
++

}

}

return size;

};

long long ans = 0;

for (int i = 0, total = 0; i < n; i++)

{

++if (!vis[i]) { // 未访问的点:说明找到了一个新的连通块
int size = dfs(i);
ans += (long) size * total;
total += size;
++

}

}

return ans;

}

};

神经网络

等变线性变换(对应代码里的 e3nn.o3.Linear ) 和 等变非线性变换(对应代码里的 e3nn.nn.Gate ) 拆开讲,它们是干啥的、有啥用:

一、先理解「等变」是啥

可以把++「等变」简单想成:输入变了、输出跟着变,++ 但变化的"规律"和输入的"对称性"能对应上。

举个生活例子:

你给一张对称的蝴蝶图片,先旋转 90 度,再用神经网络处理;

和你先处理原图,再旋转 90 度 ------ 这两种操作后,结果应该能对应上(蝴++蝶该对称还对称、该在哪还在哪)++。

这种"++输入变、输出也按相同规律变++"的性质,就是「等变」的核心。

二、等变线性变换(e3nn.o3.Linear)

把它想成「保持对称性的"线性接力"」。

比如你有一组数据,本身带着 3D 空间的对称规律(像球、立方体这些对称物体的数据),经过这个变换后,数据能"按对称规则"被线性拉伸、组合,但原本的对称性质不会乱套。

类比生活:你给一个对称的魔方拍张照,用这个变换处理照片++,魔方的"对称块"会按规律移动/组合,但魔方整体的对称结构还能看出来,++不会变成乱糟糟的图案。

实现逻辑(不用深究数学,理解思路):

基于「不可约表示(Irreps)」这些数学工具(代码里也提到了)

++保证变换时,不同"对称分量"各自线性变换,互不干扰破坏整体对称。++

就像给魔方每个面的颜色做"线性调整",但面与面的对称关系不变。

三、等变非线性变换(e3nn.nn.Gate)

通俗理解:

在线性变换基础上,给对称数据"加一把智能的'小锁'"。

它会++挑出数据里简单的、基础的对称特征(标量 Irreps),用这些特征去"控制"复杂的、高阶的对称特征(高阶 Irreps)的激活。++

类比生活:

你教机器人识别对称的汽车,"车门对称"是简单标量特征(好提取),++"整个车身的 3D 对称"是复杂高阶特征。++

++Gate 就像让"车门对称"这个小锁,去决定是否激活"车身 3D 对称"的判断++ ,让识别更高效。

实现逻辑(简单说):

先用简单的标量(比如某个对称方向的数值)当"开关",符合条件了,才让复杂的高阶对称特征参与运算。数学上还是靠 Irreps 这些工具,保证"开关"和"被控制的特征"都遵循 3D 对称规律。

四、应用场景 & 现实意义

应用场景:

  • 3D 图形/机器人领域:识别 3D 物体(像对称的零件、建筑结构)、让机器人理解空间对称规律(抓对称的工具更顺手)。

  • 材料科学:研究晶体(天生带对称结构)的性质,用等变网络分析原子排列的对称规律,预测材料性能。

  • 自动驾驶:识别道路上的对称标志(比如对称的车道线、交通标识),辅助判断路况。

现实意义:

让 AI 真正"理解" 3D 空间的对称规律,不再是"死记硬背图片/数据"。

++处理 3D 对称相关问题时,效率更高、结果更准,能解决传统神经网络"一遇到旋转/对称变化就失效"的痛点。++

五、总结

    • 等变线性:让数据按 3D 对称规律"规矩地线性变换",对称性质不变形。
    • 等变非线性:给对称数据加"智能开关",用简单特征控制复杂特征的激活,让模型更聪明。

它们就像++给 AI 装上"3D 对称透视眼",处理 3D 对称相关任务时,又稳又高效++ ,能帮我们在识别 3D 物体、研究材料、自动驾驶这些事儿上,做得更出色~