2612. 最少翻转操作数(平衡树)
题目的难度有一部分在于数学推导。对于某个点
i
i
i 进行反转是有一个范围的,这个范围需要考虑到边界的情况。可以的得到的一个结论是。对于窗口反转,KaTeX parse error: Expected group after '^' at position 4: i+i^̲' = R+L。
并且在c++中可以用到有序set的一些特性的,在实现上是一个红黑树。比如我们可以使用upper_bound()
和 lower_bound()
。这两者返回的都是迭代器,其中lower_bound( )
函数返回指向第一个大于等于给定值的元素的迭代器, upper_bound( )
函数返回指向第一个大于给定值的元素的迭代器。
class Solution {
public:
vector<int> minReverseOperations(int n, int p, vector<int>& banned, int k) {
// [max(k-1-i, i-k+1), min(2n-1-k-i, i+k-1)]
set<int> st[2];
// 初始化
vector<int> ans(n, -1);
queue<int> q;
q.push(p); ans[p] = 0;
unordered_set<int> ban;
for (int x:banned){
ban.insert(x);
ans[x] = -1;
}
// 考虑到奇偶性,维护两颗平衡树
for(int i = 0;i<n;i++){
if(i!=p && !ban.count(i)){
st[i%2].insert(i);
}
}
while(!q.empty()){
int cur = q.front();
q.pop();
int l = max(k-1-cur, cur-k+1);
int r = min(2*n-1-k-cur, cur+k-1);
// 如果不加 & 就会复制一份,导致超时
// 并不是复制,而至直接拿到引用
set<int>& cur_st = st[l%2];
auto it = cur_st.lower_bound(l);
// 对于迭代器的使用
// 1. 首先需要知道lower_bound得到是一个迭代器
// 2. 如果得不到合适的,就返回end,因此我们需要判断下
// 3. 对于迭代器的取值,需要用*
while(it != cur_st.end()){
int cur_v = *it;
if(cur_v > r) break;
ans[cur_v] = ans[cur]+1;
q.push(*it);
// 对于set常用的函数 insert(), erase()
it = cur_st.erase(it);
}
}
return ans;
}
};
2608. 图中的最短环
这可能是一个模板题目,实现一个最短的环。
基本的思路有两种,都是基于bfs进行操作。一个是删除边,一个是删除点。都是需要枚举起始点。
对于删除边,就对于两个连通的边,我们进行bfs操作。对于起点 i i i,我们如果能第二次访问到点 i i i,就说明存在环,并且bfs的特性保证一定是第一次最短的。
class Solution {
public:
int findShortestCycle(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);
}
// 初始化一个数组
int dis[n];
auto bfs = [&](int i){
// 初始化一个数组
memset(dis, -1, sizeof(dis));
dis[i] = 0;
queue<pair<int, int>> q;
// emplace 方法构造一个对应的pair
q.emplace(i, -1);
while(!q.empty()){
// 使用auto的方法,自动定位正确的cur和fa的类型
auto [cur, fa] = q.front(); q.pop();
for (int y: g[cur]){
if (dis[y] == -1){
dis[y] = dis[cur] + 1;
q.emplace(y, cur);
}else{
if (fa == y) continue;
return dis[cur] + dis[y] +1;
}
}
}
return INT_MAX;
};
int ans = INT_MAX;
for(int i = 0;i<n;i++){
ans = min(ans, bfs(i));
}
return ans==INT_MAX? -1: ans;
}
};