给你一个大小为 rows x cols 的矩阵 mat,其中 mat[i][j] 是 0 或 1,请返回 矩阵 mat 中特殊位置的数目 。
特殊位置 定义:如果 mat[i][j] == 1 并且第 i 行和第 j 列中的所有其他元素均为 0(行和列的下标均 从 0 开始 ),则位置 (i, j) 被称为特殊位置。
class Solution {
public:
bool check(vector<vector<int>>& mat,int x,int y) {
int n = mat.size(),m = mat[0].size();
for(int i = 0;i < n;i++) {
if(i == x) continue;
if(mat[i][y] == 1) return false;
}
for(int i = 0;i < m;i++) {
if(i == y) continue;
if(mat[x][i] == 1) return false;
}
return true;
}
int numSpecial(vector<vector<int>>& mat) {
int ans = 0;
int n = mat.size(),m = mat[0].size();
for(int i = 0;i < n;i++) {
for(int j = 0;j < m;j++) {
if(mat[i][j] == 1) {
if(check(mat,i,j)) ans++;
}
}
}
return ans;
}
};
给你一份 n 位朋友的亲近程度列表,其中 n 总是 偶数 。
对每位朋友 i,preferences[i] 包含一份 按亲近程度从高到低排列 的朋友列表。换句话说,排在列表前面的朋友与 i 的亲近程度比排在列表后面的朋友更高。每个列表中的朋友均以 0 到 n-1 之间的整数表示。
所有的朋友被分成几对,配对情况以列表 pairs 给出,其中 pairs[i] = [xi, yi] 表示 xi 与 yi 配对,且 yi 与 xi 配对。
但是,这样的配对情况可能会是其中部分朋友感到不开心。在 x 与 y 配对且 u 与 v 配对的情况下,如果同时满足下述两个条件,x 就会不开心:
x 与 u 的亲近程度胜过 x 与 y,且
u 与 x 的亲近程度胜过 u 与 v
返回 不开心的朋友的数目 。
思路:
直接模拟
class Solution {
public:
int a[505][505];
int vis[505];
bool check(int x,int y,int u,int v) {
if(a[x][u] > a[x][y] && a[u][x] > a[u][v]) return true;
return false;
}
int unhappyFriends(int n, vector<vector<int>>& preferences, vector<vector<int>>& pairs) {
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));
int m = n - 1;
for(int i = 0;i < n;i++) {
for(int j = 0;j < m;j++) {
a[i][preferences[i][j]] = m - j;
}
}
int ans = 0;
for(int i = 0;i < pairs.size();i++) {
for(int j = 0;j < pairs.size();j++) {
if(i == j) continue;
int x = pairs[i][0],y = pairs[i][1];
int u = pairs[j][0],v = pairs[j][1];
if(check(x,y,u,v) || check(x,y,v,u)) vis[x] = 1;
if(check(y,x,u,v) || check(y,x,v,u)) vis[y] = 1;
}
}
for(int i = 0;i < n;i++) if(vis[i]) ans++;
return ans;
}
};
给你一个points 数组,表示 2D 平面上的一些点,其中 points[i] = [xi, yi] 。
连接点 [xi, yi] 和点 [xj, yj] 的费用为它们之间的 曼哈顿距离 :|xi - xj| + |yi - yj| ,其中 |val| 表示 val 的绝对值。
请你返回将所有点连接的最小总费用。只有任意两点之间 有且仅有 一条简单路径时,才认为所有点都已连接。
思路:
最小生成树裸题
struct Edge {
int x,y,d;
bool operator < (const Edge&rhs) const {
return d < rhs.d;
}
};
class Solution {
public:
int fa[1005];
vector<Edge>vec;
int dis(int x1,int y1,int x2,int y2) {
return abs(x1 - x2) + abs(y1 - y2);
}
int findset(int x) {
if(fa[x] == x) return x;
return fa[x] = findset(fa[x]);
}
int minCostConnectPoints(vector<vector<int>>& points) {
int n = points.size();
for(int i = 0;i < points.size();i++) fa[i] = i;
for(int i = 0;i < points.size();i++) {
for(int j = i + 1;j < points.size();j++) {
int x1 = points[i][0],y1 = points[i][1];
int x2 = points[j][0],y2 = points[j][1];
int d = dis(x1,y1,x2,y2);
vec.push_back({
i,j,d});
}
}
sort(vec.begin(),vec.end());
int cnt = 0;
int ans = 0;
for(int i = 0;i < vec.size();i++) {
int x = vec[i].x,y = vec[i].y,d = vec[i].d;
int rx = findset(x),ry = findset(y);
if(rx != ry) {
cnt++;
fa[rx] = ry;
ans += vec[i].d;
}
if(cnt >= n - 1) break;
}
return ans;
}
};
给你两个字符串 s 和 t ,请你通过若干次以下操作将字符串 s 转化成字符串 t :
选择 s 中一个 非空 子字符串并将它包含的字符就地 升序 排序。
比方说,对下划线所示的子字符串进行操作可以由 “14234” 得到 “12344” 。
如果可以将字符串 s 变成 t ,返回 true 。否则,返回 false 。
一个 子字符串 定义为一个字符串中连续的若干字符。
思路:
比赛的时候没写出来嘤嘤嘤。
比赛的时候想的很复杂,用了线段树维护,后来感觉和逆序对有关(因为相同数字连线,看起来就像是二维偏序),但其实就是个思维题。
题目是选择一段,将其排序,不过并没有可行的数据结构维护这个过程。
可以简化这个操作,其实就是选择相邻两个数A,B,如果A>B那么就可以交换,那么只要A前面没有数字比A小,A就可以交换到前面任意位置。
那么考虑 t t t数列中第一个数字在 s s s数列中出现的位置,只要这个位置前面没有出现过比他小的数,那么就说明那个数可以移动过来,然后删掉这个数。
对于 t t t数列中后面的数字也是相同的考虑,这就类似划分子问题了,你把已经匹配的数删掉,那么每次相当于都是考虑要把 s s s数组中那个对应 t t t数组最前面的数移到最前面来。
class Solution {
public:
queue<int>q[20];
bool isTransformable(string s, string t) {
int n = s.size();
for(int i = 0;i < n;i++) {
q[s[i] - '0'].push(i);
}
for(int i = 0;i < n;i++) {
//如果没有数了肯定变不了
if(q[t[i] - '0'].empty()) return false;
//每个数可以往前移动到任意位置,直到前面所有数都比他小
//同理也可以往后移动到任意位置,直到后面所有数都比他大
for(int j = 0;j < t[i] - '0';j++) {
if(!q[j].empty() && q[j].front() < q[t[i] - '0'].front()) return false;
}
q[t[i] - '0'].pop();
}
return true;
}
};