Rank
A. 二进制矩阵中的特殊位置
暴力求解.
class Solution {
public:
int numSpecial(vector<vector<int>>& mat) {
int n=mat.size();
int m=mat[0].size();
int ans=0;
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
if(!mat[i][j]) continue;
bool ok=true;
for(int r=0;r<n;++r) if(r!=i && mat[r][j]) ok=false;
for(int c=0;c<m;++c) if(c!=j && mat[i][c]) ok=false;
if(ok) ++ans;
}
}
return ans;
}
};
B. 统计不开心的朋友
建立 n 个结点的完全图,边权为朋友之间的重要程度,然后对于每对 pair 中的每个人,再枚举所有其他 pair,检查是否会让此人不开心.
class Solution {
public:
int g[505][505];
int unhappyFriends(int n, vector<vector<int>>& preferences, vector<vector<int>>& pairs) {
for(int u=0;u<n;++u){
int cur=n-1;
for(int j=0;j<n-1;++j){
int v=preferences[u][j];
g[u][v]=cur--;
}
}
int ans=0;
for(int i=0;i<n/2;++i){
int x=pairs[i][0],y=pairs[i][1];
for(int j=0;j<n/2;++j){
if(j==i) continue;
int u=pairs[j][0],v=pairs[j][1];
if((g[x][u]>g[x][y] && g[u][x]>g[u][v]) || (g[x][v]>g[x][y] && g[v][x]>g[v][u]) ){
++ans;
break;
}
}
for(int j=0;j<n/2;++j){
if(j==i) continue;
int u=pairs[j][0],v=pairs[j][1];
if((g[y][u]>g[y][x] && g[u][y]>g[u][v]) || (g[y][v]>g[y][x] && g[v][y]>g[v][u]) ){
++ans;
break;
}
}
}
return ans;
}
};
C. 连接所有点的最小费用
最小生成树裸题,kruscal 算法.
class Solution {
public:
struct Edge{
int u,v,w;
Edge(int uu=0,int vv=0,int ww=0):u(uu),v(vv),w(ww){}
bool operator<(const Edge& e)const{
return w<e.w;
}
};
int n,m,par[1005];
vector<Edge> edges;
int findst(int x){
if(x==par[x]) return x;
return par[x]=findst(par[x]);
}
int minCostConnectPoints(vector<vector<int>>& points) {
n=points.size();
for(int i=0;i<n;++i){
for(int j=i+1;j<n;++j){
int w=abs(points[i][0]-points[j][0])+abs(points[i][1]-points[j][1]);
edges.push_back(Edge(i,j,w));
}
}
m=edges.size();
sort(edges.begin(),edges.end());
for(int i=0;i<=n;++i) par[i]=i;
int ans=0,cnt=0;
for(int i=0;i<m && cnt<n-1;++i){
int ru=findst(edges[i].u);
int rv=findst(edges[i].v);
if(ru!=rv){
ans+=edges[i].w;
par[ru]=rv;
++cnt;
}
}
return ans;
}
};
D. 检查字符串是否可以通过排序子字符串得到另一个字符串
CodeForces-1187D 的简化版,对长度为 2 的连续区间进行排序其实就相当于冒泡排序,可以将最小的元素移动到最前面同时保持其它元素的相对位置不发生改变.
回到这道题目中,从前向后依次遍历目标串 t
,如果发现 s[i]!=t[i]
,那么就要在 i
之后找到一个最近的 j
,使得 s[j]=t[i]
,这样就可以使用冒泡排序把 s[j]
交换到下标 i
的位置,但是有个前提那就是 s[i],s[i+1]...s[j-1]
当中一定不能有比 s[j]
更小的元素,否则是 s[j]
是无法移动到 i
位置的.
CodeForces-1187D 给出的是一个整数序列,数值不再局限为 [0,9],需要使用线段树维护区间最值来进行进一步处理.
class Solution {
public:
bool isTransformable(string s, string t) {
int len=s.size();
queue<int> que[10];
for(int i=0;i<len;++i) que[s[i]-'0'].push(i);
for(int i=0;i<len;++i){
int d=t[i]-'0';
if(que[d].empty()){
return false;
}
for(int j=0;j<d;++j){
if(!que[j].empty() && que[j].front()<que[d].front()) return false;
}
que[d].pop();
}
return true;
}
};