lcr155
中序遍历二叉搜索树,用++前驱指针串成双向链表++,再把首尾节点相连形成循环链表,返回最小节点
class Solution
{
public:
Node* treeToDoublyList(Node* root)
{
if (!root) return nullptr;
Node* ret = nullptr;
Node* pre = nullptr;
// 记录中序遍历的前一个节点
int mn=INT_MAX;
auto dfs=[&](this auto&& dfs,Node* node)
{
if (!node) return;
dfs(node->left); // 中序遍历先左子树
if(node->val<mn) {
mn=node->val;
ret=node;
}
// 构建双向链表
node->left = pre;
if (pre) pre->right = node;
pre = node;
dfs(node->right);
};
dfs(root);
// 构建循环链表(首尾相连)
pre->right = ret;
ret->left = pre;
return ret;
}
};
lc3108
在n个节点的带权无向图中,对每个查询的起点 s_i 和终点 t_i ,++求两点间旅途的边权按位与的最小值++(无旅途则返回-1,旅途可重复走边/节点)
dfs
DFS遍历图划分连通块,++计算每个连通块内所有边权的按位与值,查询两点是否连通并返回对应结果++(连通返回按位与值,不连通返回-1)
class Solution {
public:
vector<int> minimumCost(int n, vector<vector<int>>& edges, vector<vector<int>>& query) {
vector<vector<pair<int,int>>> g(n);
for(auto& v:edges)
{
g[v[0]].push_back({v[1],v[2]});
g[v[1]].push_back({v[0],v[2]});
}
vector<int> cc_and;
vector<int> ids(n,-1);
auto dfs=[&](auto&& dfs,int x)->int
{
ids[x]=cc_and.size();
int and_=-1;
for(auto& [nex,val]:g[x])
{
and_&=val;
if(ids[nex]==-1)
{
and_&=dfs(dfs,nex);
}
}
return and_;
};
for(int i=0;i<n;i++)
{
if(ids[i]==-1)
cc_and.push_back(dfs(dfs,i));
}
vector<int> ans;
for(auto& q:query)
{
++if(q[0]==q[1]) ans.push_back(0);++
else
{
ans.push_back(ids[q[0]]!=ids[q[1]]?-1:cc_and[ids[q[0]]]);
}
}
return ans;
}
};
++并查集合并图中节点,维护连通块内所有边权的按位与值++
查询两点连通性并返回对应连通块的按位与值(不连通则返回-1)
class Solution {
public:
vector<int> fa;
vector<int> and_;
int find(int x)
{
if(fa[x]!=x)
{
fa[x]=find(fa[x]);
}
return fa[x];
}
vector<int> minimumCost(int n, vector<vector<int>>& edges, vector<vector<int>>& query) {
for(int i=0;i<n;i++)
{
fa.push_back(i);
and_.push_back(-1);
}
for(auto& v:edges)
{
int fx=find(v[0]);
int fy=find(v[1]);
and_[fy]&=v[2];
if(fx!=fy)
{
and_[fy]&=and_[fx];
fa[fx]=fy;
}
}
vector<int> ans;
for(auto& q:query)
{
++if(q[0]==q[1]) ans.push_back(0);++
else
{
ans.push_back(find(q[0])==find(q[1])?and_[find(q[0])]:-1);
}
}
return ans;
}
};