Leetcode 第274场周赛题解(C++版)
Problem A - 检查是否所有 A 都在 B 之前
题意
问字符串中是否所有’a’都在’b’之前
思路
检查最后一个’a’前面是否有’b’即可
代码
class Solution {
public:
bool checkString(string s) {
int a=0,n=s.size();
for(int i=0;i<n;i++)
if(s[i]=='a') a=i;
for(int i=0;i<n;i++)
if(s[i]=='b'&&i<a) return false;
return true;
}
};
Problem B - 银行中的激光束数量
题意
给定一个01矩阵,0为空,1表示其所在位置有一个安全设备,对任意两个安全设备而言,如果同时满足下面两个条件,则二者之间存在 一个激光束:
- 两个设备位于两个不同行: r 1 r_1 r1 和 r 2 r_2 r2 ,其中 r 1 < r 2 r_1 < r_2 r1<r2 。
- 满足 r 1 < i < r 2 r1 < i < r2 r1<i<r2的所有行 i i i,都没有安全设备 。
问有多少条激光束
思路
我们只需记录含’1’的行和其含’1’的数量,对于两个满足条件的行来说,它们之间的激光束数量就等于它们’1’的数量的乘积。
代码
class Solution {
public:
int numberOfBeams(vector<string>& bank) {
int m=bank.size(),n=bank[0].size();
vector<int> v;
for(int i=0;i<m;i++){
int sum=0;
for(int j=0;j<n;j++)
sum+=(bank[i][j]=='1');
if(sum) v.push_back(sum);
}
if(v.size()<=1) return 0;
int sz=v.size(),ans=0;
for(int i=0;i<sz-1;i++){
ans+=(v[i]*v[i+1]);
}
return ans;
}
};
Problem C - 摧毁小行星
题意
给定一个整数表示初始小行星质量,小行星能摧毁质量小于等于它的其它行星,并获得其质量,现在给你一堆小行星的质量,问你能否全部摧毁。
思路
显然我们可以按照质量从小到大来摧毁小行星,类似于球球大作战哈哈,我们当然是需要尽量让自己变大,当前能变得最大的就是把比自己质量小的都吃掉,我们可以贪心地从小到大去摧毁小行星,因为这样可以保证能把质量小于等于自己的小行星先摧毁了,再去碰大的。
需要注意的点是质量需要用long long 来存,否则会超过int的范围。
代码
class Solution {
public:
bool asteroidsDestroyed(int mass, vector<int>& a) {
sort(a.begin(),a.end());
long long sum=mass;
for(int i=0;i<a.size();i++){
if(sum>=a[i]) sum+=a[i];
else return false;
}
return true;
}
};
Problem D - 参加会议的最多员工数
题意
给定一个有向图,边 { u , v } \{u,v\} {u,v}代表的是 u u u喜欢 v v v,现在让你从 n n n个点选取 m m m个点围成一个圈,圈上的每个点都必须至少和它相邻的一个点有"喜欢"的关系,问最大的 m m m值
思路
首先我们显然能想到该问题和环有关,对于长度大于2的环,显然能够恰好将环上所有点围成一个符合题意的圈,且无法再加入其他的点;但是对于长度等于2的环,由于围成环之后每个点的旁边只被占据了一个位置,所以能够加入其它的点,故而我们对上述两种情况做如下思考:
- 对于所有长度大于2的环,取最大值,若没有长度等于2的环,则答案就是最大环的点数
- 对于所有长度等于2的环,设上面两个点分别为
x
1
,
x
2
x_1,x_2
x1,x2,显然,我们可以选取一条终点为
x
1
x_1
x1的链,让上面的点依次排在
x
1
x_1
x1的旁边,同时,也可以选取一条终点为
x
2
x_2
x2的链,让上面的点依次排在
x
1
x_1
x1的旁边,具体可以看看下面的示意图,
x
2
−
n
o
d
e
1
−
n
o
d
e
2
x_2-node_1-node_2
x2−node1−node2显然是可以排在一起的,那么我们只需要分别找到以
x
1
,
x
2
x_1,x_2
x1,x2为终点的最长链,并按照上面说的方法排在一起即可。

于是,我们可以分别讨论上述两种情况,取最大值即可。
代码
class Solution {
public:
vector<int> vis;//记录访问情况
/*
在寻找环的dfs中,-1表示已访问,0表示未访问,1表示正在访问
在寻找链的dfs中,1表示已访问,0表示未访问
*/
vector<int> cyc,c1;//记录当前环、最大环
vector<pair<int,int>> p2;//记录长度为2的环
int ans,res,mx;
vector<int> G[100005];//反向建图,方便从长度为2的环找最长链
void dfs(int now,vector<int>& a){
vis[now]=1;
cyc.push_back(now);
if(vis[a[now]]==0)//目标点
dfs(a[now],a);
else if(vis[a[now]]==1){
int cnt=0;
int m=cyc.size();
for(int i=m-1;;i--){//当前环
//cout<<cyc[i]<<' ';
cnt++;
if(cyc[i]==a[now]) break;
}
//cout<<endl;
if(cnt==2)//记录长度为2的环
p2.push_back({cyc[m-1],cyc[m-2]});
if(cnt>mx){//更新最大环并用c1存储
mx=cnt;//最大环长度
c1=cyc;
}
}
vis[now]=-1;
cyc.pop_back();
}
void dfs1(int now,int len){//寻找与长度为2的环相连的最长链
vis[now]=1;
res=max(res,len);//记录最大链长度
for(int i=0;i<G[now].size();i++)
if(!vis[G[now][i]]) dfs1(G[now][i],len+1);
}
int maximumInvitations(vector<int>& a) {
int n=a.size();
vis.resize(n);
mx=0;//最大环长度
for(int i=0;i<n;i++)//初始化
G[i].clear(),vis[i]=0;
for(int i=0;i<n;i++)
G[a[i]].push_back(i);
for(int i=0;i<n;i++)//dfs最大环
if(vis[i]!=-1) dfs(i,a);
//c1存储最大环
ans=0;
if(!p2.empty()){//处理长度为2的环
int tmp=0;
for(auto p:p2){
for(int i=0;i<n;i++) vis[i]=0;
vis[p.first]=vis[p.second]=1;
res=1;
dfs1(p.first,1);
tmp+=res;
for(int i=0;i<n;i++) vis[i]=0;
vis[p.first]=vis[p.second]=1;
res=1;
dfs1(p.second,1);
tmp+=res;
}
ans=max(tmp,ans);//更新所有与长度为2的环有关的答案,取最大值
}
return max(ans,mx);
}
};
这篇博客分享了LeetCode第274场周赛的四道编程题目,包括检查字符串中'a'是否都在'b'之前、计算银行中的激光束数量、判断能否摧毁所有小行星以及求解参加会议的最大员工数。通过C++代码详细解析了解题思路和实现方法。
781

被折叠的 条评论
为什么被折叠?



